Introducción a la Programación

Anuncio
FT
Introducción a la Programación
Gerardo M. Sarria M. - Mario Julián Mora
DR
A
Borrador de 3 de agosto de 2012
FT
DR
A
Este libro fue creado usando LATEX.
Ningún animal fue maltratado durante el desarrollo de este escrito.
c 2012 - Gerardo M. Sarria M. y Mario Julián Mora
Copyright FT
DR
A
Dedicado a las todas las hamburguesas y las gaseosas del mundo...
DR
A
FT
Índice de figuras
Índice de cuadros
Índice de algoritmos
FT
Índice general
7
9
11
13
13
14
16
2. Noción de Sistema
2.1. Sistema . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.2. Observación . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.3. Ejercicios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
19
19
24
27
3. Noción de Estado
3.1. Estado . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3.2. Ejercicios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
29
29
37
4. Noción de Abstracción
4.1. Abstracción de Control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4.2. Ejercicios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
39
39
52
5. Noción de Condición
5.1. Condición . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5.2. Ejercicios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
53
53
63
6. Noción de Repetición
6.1. Iteración . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
6.2. Recursión . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
6.3. Ejercicios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
65
65
74
83
DR
A
1. Introducción
1.1. Sobre este libro . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1.2. Sobre los algoritmos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1.3. Para los profesores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5
Índice general
7. Noción de Abstracción de Datos
87
7.1. Listas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
7.2. Ejercicios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108
111
DR
A
FT
Bibliografı́a
6
FT
Índice de figuras
Sistema Solar . . . . . . . . . . . . . . . . . . . . . . .
Cajero electrónico . . . . . . . . . . . . . . . . . . . .
Wiimote y consola Wii . . . . . . . . . . . . . . . . . .
Algunos sistemas y un modelo computacional de ellos
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
19
20
21
23
3.1.
3.2.
3.3.
3.4.
3.5.
3.6.
Mundo de la Tortuga . . . . . . . . . . . . . . . . . . .
Cambios de estado en el Mundo de la Tortuga . . . . .
Estado inicial y final para dibujar una persona . . . .
Problema de sacar la tortuga del laberinto . . . . . . .
Solución al problema de sacar la tortuga del laberinto
Problema de llevar la tortuga donde su mamá . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
30
31
33
36
36
38
DR
A
2.1.
2.2.
2.3.
2.4.
4.1. Resultado de aplicar el algoritmo para dibujar una casa cuatro veces . . . . 43
4.2. Resultado esperado de aplicar el algoritmo para dibujar una casa cuatro veces 44
5.1.
5.2.
5.3.
5.4.
Estado inicial del problema de mayorı́a de edad . . . . .
Los dos posibles casos del problema de mayorı́a de edad
Flujo de ejecución de la función esMayorDeEdad() . . .
Tablero de tiro al blanco . . . . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
55
56
57
58
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
68
69
75
77
78
78
79
79
81
82
7.1. Juego Ahorcado . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
88
6.1. Flujo de ejecución de la función adivinar() . .
6.2. Posiciones del juego Triqui . . . . . . . . . . . .
6.3. Fractal . . . . . . . . . . . . . . . . . . . . . . .
6.4. Flujo de ejecución de la función factorial(5)
6.5. Torres de Hanoi - Configuración inicial . . . . .
6.6. Torres de Hanoi - Configuración final . . . . . .
6.7. Torres de Hanoi - Configuración intermedia 1 .
6.8. Torres de Hanoi - Configuración intermedia 2 .
6.9. Torres de Hanoi - Proceso completo para n = 4
6.10. Triángulo de Sierpinski . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
7
ÍNDICE DE FIGURAS
Saludo Inicial en el juego Ahorcado
Etapas del ahorcado . . . . . . . .
Estados finales del juego ahorcado
Buscaminas en Windows 7 . . . . .
Ventana del juego de las elecciones
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
. 92
. 96
. 99
. 103
. 109
DR
A
FT
7.2.
7.3.
7.4.
7.5.
7.6.
8
FT
Índice de cuadros
3.1. Operaciones básicas en el Mundo de la Tortuga . . . . . . . . . . . . . . . .
3.2. Operaciones de colores en el Mundo de la Tortuga . . . . . . . . . . . . . .
33
37
4.1.
4.2.
4.3.
4.4.
.
.
.
.
46
48
49
50
5.1. Operaciones y constantes clásicas de un sistema Booleano . . . . . . . . . .
5.2. Operaciones básicas de un sistema de números aleatorios . . . . . . . . . . .
5.3. Operaciones básicas de un sistema de cadenas de texto . . . . . . . . . . . .
54
59
62
6.1. Operaciones básicas de entrada y salida . . . . . . . . . . . . . . . . . . . .
6.2. Operaciones básicas del sistema Tkinter . . . . . . . . . . . . . . . . . . . .
6.3. Operaciones para dibujar en un Canvas de Tkinter . . . . . . . . . . . . . .
69
81
84
7.1.
7.2.
7.3.
7.4.
7.5.
90
91
94
94
96
DR
A
Operaciones de posicionamiento y orientación en el Mundo de la Tortuga
Operaciones y constantes clásicas de un sistema matemático . . . . . . . .
Porcentaje de notas de un curso Introducción a la Programación . . . . .
Operación de escritura en el Mundo de la Tortuga . . . . . . . . . . . . .
Operaciones
Operaciones
Operaciones
Operaciones
Operaciones
básicas
básicas
básicas
básicas
básicas
del sistema de listas . . . . . . . . . . . . . . . . . . .
y algunas constantes del sistema Pygame . . . . . . .
del módulo de fuentes en el sistema Pygame . . . . .
del módulo de superficies en el sistema Pygame . . .
del módulo de rutas de archivos del sistema operativo
.
.
.
.
.
9
DR
A
FT
ÍNDICE DE CUADROS
10
FT
Índice de algoritmos
DR
A
1.1. Carga del sistema matemático . . . . . . . . . . . . . . . . . . . . . . . . . .
1.2. Carga del sistema de la Tortuga . . . . . . . . . . . . . . . . . . . . . . . . .
3.1. Dibuja una persona . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3.2. Sale del laberinto cuadrado . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4.1. Dibuja las extremidades de una persona . . . . . . . . . . . . . . . . . . . . .
4.2. Dibuja el tronco de una persona . . . . . . . . . . . . . . . . . . . . . . . . .
4.3. Dibuja la cabeza de una persona . . . . . . . . . . . . . . . . . . . . . . . . .
4.4. Dibuja completamente una persona . . . . . . . . . . . . . . . . . . . . . . .
4.5. Dibuja una casa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4.6. Dibuja cuatro casas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4.7. Dibuja una casa con posición . . . . . . . . . . . . . . . . . . . . . . . . . . .
4.8. Dibuja cuatro casas especificando las posiciones . . . . . . . . . . . . . . . .
4.9. Dibuja la letra A . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4.10. Retorna la nota final del curso . . . . . . . . . . . . . . . . . . . . . . . . . .
4.11. Escribe la nota final del curso . . . . . . . . . . . . . . . . . . . . . . . . . .
4.12. Retorna la longitud de la hipotenusa de un triángulo rectángulo . . . . . . .
4.13. Retorna el dı́a del Domingo de Pascua . . . . . . . . . . . . . . . . . . . . . .
5.1. Retorna si un número es mayor o igual a 18 . . . . . . . . . . . . . . . . . . .
5.2. Retorna el puntaje dado un disparo . . . . . . . . . . . . . . . . . . . . . . .
5.3. Simula un juego de tiro al blanco . . . . . . . . . . . . . . . . . . . . . . . . .
5.4. Escribe correctamente la fecha del domingo de Pascua . . . . . . . . . . . . .
5.5. Retorna el medio de transporte para ir a un sitio de acuerdo a unas condiciones
6.1. Juego de adivinar un número, sin ciclo . . . . . . . . . . . . . . . . . . . . .
6.2. Juego de adivinar un número, con ciclo . . . . . . . . . . . . . . . . . . . . .
6.3. Juego de Triqui incompleto . . . . . . . . . . . . . . . . . . . . . . . . . . . .
6.4. Desglose de dinero . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
6.5. Imprime la lista de número primos entre 1 y n . . . . . . . . . . . . . . . . .
6.6. Recibe lı́neas de código y quita los comentarios . . . . . . . . . . . . . . . . .
6.7. Halla el factorial de un número n . . . . . . . . . . . . . . . . . . . . . . . .
6.8. Imprime el proceso para solucionar las torres de hanoi de n discos . . . . . .
6.9. Dibuja el triángulo de Sierpinski . . . . . . . . . . . . . . . . . . . . . . . . .
7.1. Juego ahorcado . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
14
15
34
35
40
40
41
41
42
43
45
46
47
49
49
50
51
56
59
60
61
63
66
67
70
71
72
74
76
80
83
89
11
ÍNDICE DE ALGORITMOS
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
pistas .
que no
. . . . .
93
95
97
98
100
101
102
104
105
106
107
DR
A
FT
7.2. Pantalla de inicio del juego ahorcado . . . . . . . . . . . . . . . . .
7.3. Dibuja/Actualiza la pantalla principal del juego ahorcado . . . . . .
7.4. Retorna la letra que el usuario presione en el juego ahorcado . . . .
7.5. Termina el juego ahorcado . . . . . . . . . . . . . . . . . . . . . . .
7.6. Simulador de elecciones . . . . . . . . . . . . . . . . . . . . . . . . .
7.7. Retorna un candidato en el juego de elecciones . . . . . . . . . . . .
7.8. Ordena las listas de candidato y votos en el juego de elecciones . . .
7.9. Juego buscaminas . . . . . . . . . . . . . . . . . . . . . . . . . . . .
7.10. Crea y retorna una matriz de dimensiones ancho × alto . . . . . . .
7.11. Llena el tablero del buscaminas con minas y pistas . . . . . . . . . .
7.12. Modificación del algoritmo para llenar el tablero del buscaminas con
7.13. Función que determina si se han descubierto todas las ubicaciones
tienen mina . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
12
108
FT
1 Introducción
DR
A
La programación se ha convertido en una ciencia básica. Su importancia dentro de todas
las ingenierı́as se ha vuelto notoria dado que cualquiera de las corrientes de ingenierı́a tiene
componentes que involucran nociones de programación: problemas que pueden ser resueltos
siguiendo una serie de pasos (noción de algoritmo), variables que deben ser tomadas en
cuenta al realizar observaciones, datos que deben ser procesados, e incluso el mismo uso
del computador.
En las actividades cotidianas de los adolescentes actuales también podemos ver nociones
de programación: comprar un reproductor mp3, descargar una canción de internet (de las
que sı́ se pueden descargar sin romper ninguna ley) y copiarla en el reproductor, practicar
un deporte, etc. Mucho más en actividades más cercanas a las profesiones de ingenierı́a:
construcción de una vı́a, transporte de mercancı́a, inter-conectar una red de celulares,
instalar un computador/servidor con un sistema operativo como linux, entre otros.
1.1.
Sobre este libro
La mayorı́a de libros de introducción a la programación usan la metodologı́a de enseñanza
de programación teach-a-languague, es decir, mediante un lenguaje de programación. Esta
metodologı́a presume que si el estudiante aprende un lenguaje de programación entonces
aprende a programar. Nosotros pensamos que esta metodologı́a ya no es apropiada para la
actual generación de estudiantes. Por esta razón proponemos una nueva metodologı́a y como
creemos en los métodos formales, este libro está basado en las nociones de programación
en vez de herramientas y lenguajes.
En este escrito usamos la idea del paradigma del paracaidista [1] utilizado en especificación de modelos formales de sistemas. Vamos a pasar por muchas nociones, empezando
por la de sistema, la noción de observación, la de estado, abstracción, condición, iteración,
recursión, abstracción de datos y terminando en la noción de persistencia. En este libro no
enseñamos cómo se escribe una lı́nea de código, esperamos que eso se aprenda de una manera natural. Sabemos que es necesario usar un lenguaje de programación para practicar,
de manera que usaremos Python (como veremos en la siguiente sección) ya que tenemos
confianza en que mejora el proceso de enseñanza, que es el cuarto principio en un curso
inicial a la programación [6]. Sin embargo, como veremos, el uso de Python no es el núcleo
13
1 Introducción
FT
1.2.
Sobre los algoritmos
Los algoritmos mostrados en este documento siguen la sintaxis del lenguaje de programación Python. De esta manera si se quieren probar los programas se debe instalar el
compilador del lenguaje, que puede ser descargado gratis de la página web de Python
(http://www.python.org/).
Las funciones y procedimientos que se definan tendrán la documentación permitida por
el lenguaje. Esta se especifica entre comillas debajo de la declaración de la función o
procedimiento (en color verde).
Para probar los algoritmos que usan operaciones de distintos sistemas es necesario cargar
dichos sistemas. Para cargar el sistema matemático de Python (math), por ejemplo, antes
del código es necesario agregar una lı́nea fundamental para cargar el sistema, la cual se
puede ver en el algoritmo 1.1.
DR
A
Noción
del libro porque las nociones de programación son aquellas que estarán en la vida diaria
de los estudiantes por siempre.
El profesor Edsger W. Dijkstra dijo alguna vez: “Las nociones son fundamentales en
toda actividad de programación. Ellas son tan fundamentales que no serán divididas en
conceptos más primitivos.”. Entonces para resaltarlas, las nociones de programación podrán
verse marcadas al lado del texto, como una nota al margen.
Los cuadros que se muestran en este documento describen solo unas cuantas operaciones
(a veces incompletas) que pueden aplicarse y que pertenecen a algunos sistemas desarrollados para Python. Sin embargo con ellos no pretendemos que los estudiantes tomen este
libro como un manual de referencia de las librerı́as del lenguaje, por el contrario, deseamos
que los estudiantes se motiven a consultar y estudiar más las librerı́as de Python (en su
documentación en lı́nea en http://www.python.org/doc/) de manera que sus programas
contengan mejores caracterı́sticas. El lector que desee un libro técnico sobre Python puede
ver [3] ó [4].
# Se carga el sistema matemático
import math
Algoritmo 1.1: Carga del sistema matemático
Por otro lado, para ejecutar los programas en el contexto del Mundo de la Tortuga
se debe hacer tal y como se carga el sistema matemático antes de la aplicación de cualquier operación. Adicionalmente, para que el resultado de la ejecución de los algoritmos
14
1.2 Sobre los algoritmos
sea exacto a aquellos que se muestra en este libro, se deben aplicar algunas operaciones
inmediatamente después de la carga del sistema, que se pueden ver en el algoritmo 1.2.
FT
# Se carga el sistema Mundo de la Tortuga
import turtle
# Operacion para cambiar el titulo de la ventana
turtle.title("El Mundo de la Tortuga")
# Operacion para cambiar el tamaño de la ventana
turtle.setup(500,500)
# Operacion para cambiar la forma de la Tortuga
turtle.shape("turtle")
# Operacion para reiniciar el sistema
turtle.reset()
Algoritmo 1.2: Carga del sistema de la Tortuga
DR
A
Puede notarse que para aplicar las operaciones de los sistemas es necesario anteponer
el nombre del sistema (turtle en este caso). Los sistemas que se usarán como ejemplo en
este libro se listan a continuación:
turtle – Sistema de la Tortuga
math – Sistema matemático
random – Sistema de números aleatorios
string – Sistema de cadenas de texto
Tkinter – Sistema de interfaces gráficas
pygame – Sistema de creación de juegos
os – Sistema de manejo de operaciones del sistema operativo
Adicionalmente en aquellos problemas donde se tiene un estado inicial determinado, es
necesario cargar dicho estado inicial como en la segunda lı́nea de los algoritmos anteriores
cambiando el nombre del sistema (math y turtle, respectivamente) por el nombre del
archivo sin la extensión pyc. Todos los archivos deben estár guardados en la misma carpeta.
En la página web del libro están enumerados los estados iniciales de los ejemplos y ejercicios
que los requieran.
15
1 Introducción
1.3.
Para los profesores
FT
En [5] propusimos una metodologı́a para la enseñanza de la programación. En ella nosotros concebimos un curso de Introducción a la Programación como una secuencia de
sesiones de clase. Consideramos la duración de un curso como un perı́odo de 16 semanas,
por lo que contamos con 32 sesiones de 2 horas. Tomamos entonces dos o más sesiones
para cada noción incluyendo teorı́a y práctica (esperamos que más práctica que teorı́a). A
continuación detallamos un poco la idea que proponemos con cada noción:
Sistema Nosotros pensamos la noción de sistema como un conjunto de elementos interactivos en un dominio muy especı́fico. No hay que profundizar en la definición de
la palabra sino en la aplicación del concepto. Es bueno empezar con ejemplos que
todos los estudiantes conocen como el sistema solar, el sistema digestivo y el sistema
económico. Luego se puede mover a los sistemas actuales y populares (con los que
el estudiante convive diariamente) como los cajeros automáticos, la televisión, las
consolas de juego y los computadores, por supuesto.
DR
A
La idea en esta noción es mostrar que todo lo que nos rodea es un sistema y la
mayorı́a (sino todos) de sistemas son modelables. Los programas de computador
son finalmente modelos computacionales de sistemas reales. Los estudiantes deben
identificar los elementos de los sistemas y describir sus interacciones. Es una buena idea pedir a los estudiantes que vacı́en sus bolsillos para encontrar una gran
cantidad de sistemas que sirven como material para la clase: iPods, celulares, tarjetas de crédito, CDs,/DVDs, memorias USB, etc. Adicionalmente, en la página web
http://www.howstuffworks.com/ se encuentra una cantidad suficiente de artı́culos
de los dispositivos y sistemas recientemente nombrados los cuales pueden motivar a
los estudiantes.
Se pueden emplear dos sesiones en esta noción.
Observación Una vez los estudiantes entienden un sistema, deben ser capaces de describirlo. En este punto nos interesamos en los elementos y no en el sistema como un
todo. Siguiendo el paradigma del paracaidista bajamos un poco de manera que nos
acerquemos al sistema y podamos preguntarles a los estudiantes qué es estático y
qué cambia en él. Lo que se mantiene estático lo llamaremos “una constante” y los
elementos que cambian serán llamados “variables”. Adicionalmente, para cada elemento detectamos los valores que puede tener. Este conjunto de valores define el tipo
de dato del elemento.
Esta noción no necesita mas de dos sesiones para ser entendida.
16
1.3 Para los profesores
FT
Estado Bajando un poco más en el sistema, se hace que los estudiantes noten que algunas veces unas variables tienen un valor y algunas veces ellas tienen otro valor. La
valuación de todas las variables define el estado del sistema. Los estudiantes deben
identificar cómo cambia el sistema de un estado a otro, de manera que se den cuenta
que algunas operaciones tienen que ejecutarse para cambiar los valores de las variables (y consecuentemente cambiar el estado). Aquı́ es donde la definición del concepto
de algoritmo surge: la secuencia de operaciones que lleva un estado a otro.
Las operaciones que se usan aquı́ pueden ser descritas en notación Python para que
los estudiantes se familiaricen con el lenguaje. En este punto las operaciones son
consideradas cajas negras con entradas y salidas. Como Python es un lenguaje de
programación tipado implı́cito, esta caracterı́stica evita el ruido que incorpora la
declaración de tipos de datos en los llamados a funciones.
DR
A
Motivamos a los profesores a que se armen de ayudas pedagógicas para que los estudiantes entiendan muy bien esta noción, la cual es vital para el éxito del aprendizaje.
Cambiar el modo de pensar de una persona hacia un pensamiento sistémico (i.e. pensar todo el tiempo en términos de secuencia de pasos, algoritmos) es muy difı́cil. Usar
el Mundo de la Tortuga, el robot LightBot (http://armorgames.com/play/2205)
ó un Lego MindStorm, son algunas alternativas.
Cuatro sesiones son una buena cantidad para esta noción. Además, este es un buen
punto para hacer una primera evaluación en el curso.
Abstracción Entre mas complejos se vuelven los problemas, más largos se vuelven los
programas. De esta manera el estudiante siente la necesidad de tener una forma de
programar con menos lı́neas de código. Ası́ se les enseña a organizar varias operaciones
en una sola. Las cajas negras se vuelven cajas blancas. Los estudiantes ahora pueden
construir sus propias operaciones llamando las básicas. Con las nuevas operaciones
ellos pueden construir otras y ası́ sucesivamente. La noción de niveles de abstracción
llega de una manera natural.
Otras cuatro sesiones pueden usarse en esta noción.
Condición Si el estado del sistema es desconocido el estudiante siente la necesidad de tener
una estructura de control para considerar varios casos. Esto hace que se introduzca la
noción de condición. Sin embargo, para entender mejor el mecanismo de esta noción
se tienen que empezar por hacer ejercicios de los fundamentos básicos de la lógica
proposicional: tablas de verdad y conectivos lógicos. Tal como las nociones anteriores
esto debe hacerse usando expresiones cercanas al conocimiento de los estudiantes.
Como las expresiones lógicas son elementos muy abstractos se deben utilizar cuatro
sesiones para esta noción. El final de esta noción es otro buen punto para hacer una
17
1 Introducción
evaluación.
Iteración Aunque pensamos que la recursión es la forma más simple de repetición ya que no
cambia el estado de las variables, parece ser más natural para los estudiantes aplicar
otra estructura de repetición que si cambie las variables. Ella es llamada iteración.
FT
En esta noción es bueno quedarse un buen tiempo (ocho sesiones) ya que las nociones
son introducidas gradualmente, y con la inclusión de una nueva noción se continúa
usando y practicando las anteriores. Además, los estudiantes ahora tienen todas las
herramientas para solucionar la mayorı́a de problemas. De allı́ que al finalizar esta
noción se pueda hacer otra evaluación.
Recursión Como dijimos arriba, nosotros creemos que la recursión es la forma básica de repetición en programación. Sin embargo esta noción puede ser muy difı́cil de entender.
Por esta razón consideramos que ella puede ser opcional.
DR
A
Nosotros simplificamos la idea considerando solo la recursión numérica y enseñando
esta noción como lo que es: un llamado a función. Sabemos que se debe enseñar todo
sobre el caso base y las reglas para reducir los otros casos, pero tal como las otras
nociones, debe hacerse con ejemplos de la vida real que los estudiantes conozcan, y
usando herramientas gráficas.
Se podrı́an usar dos o tres sesiones para practicar la recursión.
Abstracción de Datos Esta noción viene con la necesidad de agrupar una gran cantidad
de información. Se puede pedir a los estudiantes, por ejemplo, que se calcule el promedio de todas las clases que han tomado. Si el número de clases es poco entonces
no hay problema, pero si el estudiante ha tomado siete o más clases, manejar esta
cantidad de variables es inconveniente (imagine la cantidad de variables de entrada
a las funciones).
De todas las estructuras de datos hemos escogido listas por dos razones: son estructuras de datos básicas y su mecanismo de uso en Python es muy cómodo.
Usamos las últimas ocho sesiones para esta noción y se puede hacer la cuarta y última
evaluación.
Persistencia Al igual que recursión, dejamos esta noción como opcional ya que ella nace
de la necesidad de mantener los datos incluso después de ejecutar los programas.
Se debe enseñar entonces un poco sobre sistemas de archivos (sin entrar mucho en
detalle sobre los sistemas operativos) y dispositivos de almacenamiento fı́sico como
discos duros o memorias USB.
Aquı́ también se podrı́an usar dos o tres sesiones.
18
2.1.
Sistema
FT
2 Noción de Sistema
DR
A
Un sistema es un conjunto de elementos que interactúan en un dominio especı́fico y
cumplen ciertas propiedades. Dichos elementos se relacionan entre ellos y actúan con un
propósito especı́fico. El resultado del comportamiento y conectividad de los elementos describe el objetivo del sistema.
Figura 2.1: Sistema Solar
Ejemplos de sistemas pueden verse en todos los ámbitos. Entre los más conocidos tenemos
el sistema solar, el sistema digestivo y el sistema económico. La figura 2.11 muestra el
sistema solar. En este sistema el conjunto de elementos está compuesto por el Sol, los ocho
1
Imagen tomada de http://www.ifir.edu.ar/planetario/nssolar.htm/
19
Sistema
2 Noción de Sistema
FT
planetas, los cinco planetas enanos y otra cantidad de astros. Todos estos elementos se
relacionan entre sı́ por medio de la gravedad del Sol, la cual ocasiona que los planetas y
astros se muevan en una órbita casi circular sobre el denominado plano eclı́ptico.
Existen otros múltiples ejemplos de sistemas que tal vez ignoramos debido a que hacen
parte de nuestra vida cotidiana y no llevan en su nombre la palabra sistema. Ejemplos de
ellos son los cajeros automáticos, la televisión, las consolas de juego y los computadores.
Los ejemplos 2.1 y 2.2 muestran algunos de estos sistemas.
DR
A
Ejemplo 2.1
La figura 2.22 muestra un ejemplo de cajero automático. Muy a grosso modo un cajero
automático es una terminal que acepta peticiones y se comunica, por medio de una red de
datos, con los computadores de un banco para atender dichas peticiones.
Figura 2.2: Cajero electrónico
Los elementos que componen el cajero son: los botones, el teclado del cajero, el lector
de tarjetas, la ranura de depósitos, la pantalla, el parlante, el dispensador de dinero y la
impresora de recibos.
Una de tantas interacciones que tiene un cajero electrónico es la siguiente: un usuario
realiza una petición por intermedio de una tarjeta que es introducida al lector de tarjetas.
Algunos cajeros, una vez acepta la tarjeta, pide a través de la pantalla y/o el parlante
2
Imagen modificada de http://www.howstuffworks.com/
20
2.1 Sistema
FT
que introduzca la clave (otros cajeros la piden justo antes de realizar la transacción). Por
medio los botones y el teclado se introduce la clave y se selecciona los datos apropiados del
menú para efectuar la transacción deseada. Si es un retiro, entonces el cajero podrı́a proveer
el dinero por medio del dispensador o podrı́a enviar un mensaje por la pantalla y/o el
parlante diciendo que no se pudo efectuar la operación (falta de dinero o alguna otra razón);
si es una consulta simplemente se muestran los datos en la pantalla; y si es una consignación
se abre la ranura de depósitos para entregar el dinero. Una vez termina cualquiera de las
transacciones anteriores, el cajero imprime un recibo y termina la interacción.
? ? ?
DR
A
Ejemplo 2.2
Wii (figura 2.33 ) es una consola de juego lanzada en 2006 por la empresa de videojuegos
Nintendo. Como toda consola de juego el Wii es un computador de entretenimiento interactivo que produce una señal de video, la cual puede ser interpretada por un televisor o
monitor.
Figura 2.3: Wiimote y consola Wii
Al igual que un computador actual, el Wii cuenta con un procesador central, un procesador de video, 88 Mb de memoria interna, una memoria flash de 512 Mb (no cuenta con
3
Imagen tomada de http://wii.com/.
21
2 Noción de Sistema
FT
disco duro), tarjetas de video y sonido, y un lector de discos, entre otras cosas.
Sin embargo, el Wii es reconocido por el Wii Remote, también conocido como Wiimote.
Este dispositivo es el control principal de la consola. El Wiimote cuenta con un sistema de
detección de movimiento en el espacio que permite manipular objetos en la pantalla, un
apuntador óptico y una serie de botones para interactuar con el usuario.
El funcionamiento del Wii es relativamente sencillo ya que la clave de la consola de
Nintendo se centra en el control. El sistema cuenta con un barra –llamada sensor bar – que
emite luz infraroja y que es detectada por el Wiimote. De esta manera el sistema determina
la posición y orientación relativa en 3D del control. El Wiimote se conecta a la consola
usando Bluetooth (la tecnologı́a abierta para el intercambio de datos entre dispositivos
electrónicos en distancias cortas). Este diseño permite a los usuarios controlar los juegos
usando movimientos corporales y las presiones de botones tradicionales.
? ? ?
DR
A
Incluso si dejamos a un lado la electrónica, podemos ver ejemplos de sistemas mucho
más simples como por ejemplo un banco (sin la parte automatizada), una sala de cine, un
club social, una biblioteca, un teléfono y una tienda de música. Todos estos son sistemas
y en cada uno de ellos se pueden identificar sus elementos e interacciones. De esta manera
podemos construir modelos de dichos sistemas.
Un modelo es la representación de un objeto o sistema. Los modelos pueden ser fı́sicos
(e.g. un carro de juguete que represente un carro real) o no fı́sicos (e.g. una ecuación
matemática que represente el movimiento del carro), pero todos tienen en común que
sirven para hacer simulaciones y probar propiedades en los sistemas.
Existe un tipo de modelo no fı́sico llamado modelo computacional. Este es un modelo
abstracto que se desarrolla en computadores y es denominado comúnmente como programa.
En la actualidad es muy frecuente el uso de dispositivos computacionales como PCs, iPads
y Blackberrys. Todos ellos pueden ejecutar programas que sirven para una tarea especı́fica.
Sin embargo, si se mira bien dichos programas, puede verse que son representaciones de
sistemas reales. El lector que esté familiarizado con programas como Skype, puede notar
que son modelos de un sistema telefónico; aquel que esté familiarizado con iTunes, podrá ver
que es un modelo de una tienda de música; Kindle es un modelo de una biblioteca; Windows
Media Player es un modelo de una sala de cine; y Facebook es un modelo de un club social.
En la figura 2.44 pueden verse otros ejemplos de sistemas reales y un modelo computacional
de cada uno de ellos.
Modelo
Programa
4
Imágenes tomadas de http://recursos.cnice.mec.es/biosfera/alumno/1ESO/planeta_habitado/
index.htm (Tierra), http://www.olympiaph.com.ph/crm/typewriters.html (máquina de escribir), y
http://www.revivesoundproductions.com/djseminar.html (dj)
22
FT
2.1 Sistema
DR
A
(a) La Tierra y Google Earth
(b) Una Máquina de Escribir y MSWord
(c) Un DJ y VirtualDJ
Figura 2.4: Algunos sistemas y un modelo computacional de ellos
23
2 Noción de Sistema
2.2.
Ejemplo 2.3
Las siguientes tablas listan las constantes y variables de los sistemas: una sala de cine, una
tienda de barrio y un rompecabezas.
DR
A
Variable
Al conocer los sistemas, existen muchas propiedades y caracterı́sticas interesantes que
podemos observar de ellos. Las descripciones que hagamos de los sistemas nos permiten
identificar los aspectos estáticos y dinámicos de ellos. Si tomamos un carro, por ejemplo,
y observamos detenidamente sus caracterı́sticas, podemos encontrar que algunas de ellas
cambian a través del tiempo, mientras que otras se quedan estáticas: la velocidad cambia, el
kilometraje cambia, el nivel de gasolina cambia, el estado del motor (encendido o apagado)
cambia y su posición geográfica cambia, mientras que la placa se mantiene, el color del
carro se mantiene (en términos generales) y la forma se mantiene (si no se choca). Muchas
otras cosas del carro cambian y muchas otras se mantienen igual a través del tiempo, sin
embargo, en primera instancia, estas son las mas notorias.
Aquellas caracterı́sticas que se mantienen igual en un sistema son llamadas constantes.
Las constantes tienen un papel muy importante en los sistemas dado que están completamente fijas y, por lo tanto, sirven como referentes.
Por otro lado, aquellos componentes que cambian de un sistema son denominados variables. En el ejemplo 2.3 se muestran algunas constantes y variables de algunos sistemas.
FT
Constante
Observación
Una sala de cine:
Constantes
Número de Sillas
Pantalla
Variables
Número de Asistentes
Pelı́cula
Configuración de los Asistentes
Un rompecabezas:
Constantes
Número de fichas
Tamaño
Forma de las fichas
Una tienda de barrio:
24
Variables
Ubicación de las fichas
2.2 Observación
Variables
Cantidad de productos
Dinero
Número de clientes
Organización de los productos
Precio de los productos
FT
Constantes
El local
El vendedor(*)
(*) Aunque el vendedor puede variar se puede decir que siempre hay un vendedor.
? ? ?
DR
A
Como se pudo notar en el ejemplo anterior, es normal que en la mayorı́a de sistemas
existan más variables que constantes. A nivel general, las variables son conjuntos lógicos
de atributos, es decir, sı́mbolos o nombres simbólicos dados a una cantidad de información.
Esta información pertenece a un dominio de valores, esto es, una asociación de datos
que se clasifican de la misma manera (e.g. números, letras, objetos). Estos dominios que
determinan los posibles valores de las variables son llamados tipos de datos 5 . En el ejemplo
del carro tenemos que las variables observadas son la velocidad, el kilometraje, el nivel de
gasolina, estado del motor y la posición geográfica. Para encontrar los tipos de datos para
estas variables hacemos el siguiente análisis:
La velocidad del carro es un valor numérico que varia dependiendo de la marca y el
modelo del carro, sin embargo tiene dos lı́mites, uno inferior y uno superior. El lı́mite
inferior es cero ya que lo mı́nimo que el carro puede hacer es quedarse quieto. Por
otro lado, el lı́mite superior es una constante k, la cual es definida en el tiempo de
diseño del carro. Un Renault Logan, por ejemplo, tiene una velocidad máxima de 185
km/h. Por lo anterior esta variable tiene el dominio de valores en el rango [0, k], y
entonces su tipo de dato es Natural.
El kilometraje es también un valor numérico que comienza en 0 (cero) cuando el carro
es nuevo y nunca ha sido manejado. Este valor se incrementa a medida que el carro
es usado y jamás decrece. De allı́ que el dominio de valores es el de los números reales
positivos, luego su tipo de dato es Real.
El nivel de gasolina es otro valor numérico similar a la velocidad. Tiene un lı́mite
inferior (cuando el carro no tiene nada de gasolina) y un lı́mite superior (cuando
el carro está “tanqueado”). La diferencia entre este dominio de valores y el de la
5
Aunque las constantes no cambian su valor, dicho valor pertenece a un dominio especı́fico y por lo tanto
podemos decir que las constantes tienen también un tipo de dato.
25
Tipo de Datos
2 Noción de Sistema
velocidad está en que el dominio del nivel de gasolina representa un porcentaje, esto
es, la variable tiene un valor entre 0 y 100. Por lo anterior el tipo de dato de la
variable nivel de gasolina es Real.
FT
El estado del motor tiene uno de dos valores posibles: encendido o apagado. Esto
quiere decir que si preguntan ¿está encendido el carro?, en la observación podemos
contestar Verdadero o Falso. Por esto su tipo de dato es Booleano6 .
La posición geográfica del carro es un poco más complicada ya que involucra dos
ejes. Estos ejes son comúnmente llamados Latitud (posición con respecto al norte o
sur del ecuador) y Longitud (posición con respecto al oriente u occidente del primer
meridiano ó Greenwich). Ellos tienen sus valores en unidades de medida angular
(UMA), es decir, grados, minutos y segundos. Entonces el tipo de datos para la
posición geográfica es UMA × UMA.
Ejemplo 2.4
Supongamos que tenemos los siguientes juegos: un buscaminas, una sopa de letras y un
ahorcado, ¿cuáles son sus variables y tipos de datos correspondientes?
DR
A
Un buscaminas:
Variable
Número de minas
Ubicación de la mina i
Número de marcas
Ubicación de la marca j
Número de espacios destapados
Espacio destapado k
Tipo de Dato
Entero
Entero × Entero
Entero
Entero × Entero
Entero
Entero × Entero
Una sopa de letras:
Variable
Número de filas
Número de columnas
Número de palabras
Letra de la ubicación i, j
Palabras encontradas
6
Tipo de Dato
Entero
Entero
Entero
Caracter
Lista de palabras
El conjunto de valores Booleanos está compuesto por dos elementos 1 (Verdadero) y 0 (Falso). Este
conjunto es la base fundamental del Álgebra Lógica de Boole, desarrollada por el matemático británico
George Boole en 1854.
26
2.3 Ejercicios
Un ahorcado:
Tipo de Dato
Lista de palabras
Entero
Caracter
Entero
Entero
Entero
Booleano
FT
Variable
Palabras
Número total de letras de la palabra
Letra correspondiente a la ubicación i
Número de letras descubiertas de la palabra
Número total de partes del muñeco
Número de partes del muñeco dibujadas
Se ahorcó
? ? ?
2.3.
Ejercicios
2.1 De los siguientes sistemas escoja cinco (5) y describa sus elementos e interacciones:
DVD Player
Casino
Kinect
Pizzerı́a
Celular
iPod
Supermercado
Estación Espacial
Dispensador de Gaseosas
Discoteca
DR
A
Carro
Gobierno
Televisor
MIO
Monopoly
Partido de Fútbol
Universidad
Minicomponente
Laboratorio de Fı́sica
Su Casa
2.2 ¿Cuáles de los anteriores sistemas tienen un modelo computacional? Provea una descripción del programa.
2.3 Tome cinco sistemas de los enumerados anteriormente (diferentes de los escogidos en
el primer ejercicio) y muestre cuáles de sus elementos son constantes y cuáles son
variables.
2.4 De los siguientes juegos determine sus variables y sus constantes, con sus respectivos
tipos de datos: blackjack, triqui, pinball.
27
DR
A
FT
2 Noción de Sistema
28
3.1.
Estado
FT
3 Noción de Estado
Las variables de un sistema cambian su valor a través del tiempo. Cada vez que una
variable cambia su valor, el estado en el cual se encuentra sistema cambia. Un estado de
un sistema es una configuración única de los elementos que componen dicho sistema. El
estado del sistema está definido entonces por la valuación de todas sus variables.
Para ejemplificar la noción de estado vamos a introducir un sistema muy simple llamado
el mundo de la tortuga:
DR
A
La tortuga vive en un mundo de dos dimensiones en el cual puede moverse.
Ella siempre inicia en el centro del mundo. Este mundo es ilimitado y el centro
de él está en la posición 0,0. La tortuga puede dibujar mientras se mueve y
sus movimientos pueden ser: ir en lı́nea recta hacia adelante ó hacia atrás una
distancia determinada, cambiar su orientación (a la izquierda o la derecha k
grados), moverse en un cı́rculo y escribir un texto. Adicionalmente la tortuga
puede desplazarse sin dibujar a una posición x, y y se le puede preguntar su
posición y orientación.
En la figura 3.1 puede verse el mundo de la tortuga. En esta figura la tortuga ha dibujado
una casita. Para llegar a este estado del sistema, se ha debido pasar por varios estados
intermedios donde se ha cambiado el valor de las variables del sistema. En la figura 3.2 se
detallan los diferentes estados.
A continuación se explica en detalle los cambios de estado de la figura 3.2.
1. Todo comienza en el estado inicial (Figura 3.2a), donde la tortuga está en el centro
del mundo (posición x = 0, y = 0) y su orientación o sentido es cero (θ = 0).
2. La tortuga se mueve luego 50 unidades hacia adelante (Figura 3.2b). Su posición ha
cambiado a x = 50, y = 0 y su orientación queda igual.
3. Después la tortuga cambia su orientación a θ = 90, pero su posición permance igual
en x = 50, y = 0 (Figura 3.2c).
4. Acto seguido (Figura 3.2d) la tortuga se desplaza 100 unidades hacia adelante quedando en x = 50, y = 100. Su orientación se mantiene en θ = 90.
29
Estado
FT
3 Noción de Estado
DR
A
Figura 3.1: Mundo de la Tortuga
5. Ahora la tortuga rota noventa grados a la izquierda sin desplazarse cambiando su
orientación a θ = 180 (Figura 3.2e).
6. Una vez más la tortuga se mueve 100 unidades hacia adelante modificando su posición
a x = −50 y y = 100 (Figura 3.2f).
7. De nuevo rota noventa grados a la izquierda sin trasladarse y su orientación es ahora
θ = 270 (Figura 3.2g).
8. Otra vez viaja la tortuga hacia adelante 100 unidades (Figura 3.2h). Su nueva posición
es x = −50 y y = 0.
9. Luego la tortuga gira noventa grados a la izquierda volviendo a su orientación inicial
θ = 0 (Figura 3.2i).
10. La tortuga termina el cuadrado yendo hacia adelante 50 unidades y finalizando en la
misma posición inicial x = 0, y = 0 (Figura 3.2j).
11. Para dibujar el techo de la casa, la tortuga primero se desplaza sin dibujar cincuenta
unidades en el eje horizontal x = 50 (Figura 3.2k).
30
(b) Estado 2
(e) Estado 5
(f) Estado 6
(c) Estado 3
(d) Estado 4
(g) Estado 7
(h) Estado 8
DR
A
(a) Estado Inicial
FT
3.1 Estado
(i) Estado 9
(j) Estado 10
(k) Estado 11
(l) Estado 12
(m) Estado 13
(n) Estado 14
(ñ) Estado 15
(o) Estado Final
Figura 3.2: Cambios de estado en el Mundo de la Tortuga
31
3 Noción de Estado
12. Después se mueve cien unidades en el eje vertical y = 100 (Figura 3.2l) también sin
dibujar.
FT
13. Como el techo tiene dos lı́neas diagonales, la tortuga tiene que rotar 135 grados
(Figura 3.2m) y cambia su orientación a θ = 135.
14. Dibuja la primera lı́nea desplazandose 70.7 unidades1 (Figura 3.2n). Su posición
cambia a x = 0 y y = 150
15. Posteriormente la tortuga rota noventa grados a la izquierda, dejando θ = 215 (Figura
3.2ñ).
16. Finalmente la tortuga se mueve otras 70.7 unidades llegando al estado final x = −50,
y = 100 y θ = 215 (Figura 3.2o).
DR
A
Algoritmo
Los anteriores son los pasos para llevar el sistema del estado inicial al estado final. De
manera general, el conjunto ordenado de pasos que llevan un sistema de un estado a otro
es comúnmente llamado algoritmo. Los pasos que se ejecutan en un algoritmo realizan
operaciones que modifican las variables del sistema y, por ende, el estado del mismo. Las
operaciones son acciones que pueden efectuarse dentro del sistema y son definidas en el
tiempo de creación del sistema. Para el caso del mundo de la tortuga, el conjunto núcleo
de operaciones2 se encuentra en el cuadro 3.1.
Comentario
Ejemplo 3.1
Dados los estados inicial y final en la figura 3.3, ¿cuáles son las operaciones necesarias para
llevar al sistema del estado inicial al estado final?
El algoritmo 3.1 muestra los pasos para llevar el sistema de un estado al otro. Las lı́neas
rojas que comienzan con el sı́mbolo ’#’ son denominados comentarios. Los comentarios
son anotaciones en algoritmos que sirven para documentar el código y hacerlo más fácil de
entender, pero que no se tienen en cuenta a la hora de ejecutar el algoritmo.
1
? ? ?
Este valor es determinado fácilmente aplicando el teorema de Pitágoras: En todo triángulo rectángulo el
cuadrado de la hipotenusa es igual a la suma de los√cuadrados de los catetos. Como los catetos de este
triángulo miden 50 unidades se tiene entonces d = 502 + 502 = 70,7.
2
Existen muchas más acciones que se irán introduciendo a medida que se necesiten.
32
3.1 Estado
left(a)
penup()
pendown()
position()
heading()
undo()
clear()
home()
reset()
Acción
Avanza u pixeles (dibuja dependiendo del estado del lápiz)
En la posición actual realiza una porción del un cı́rculo de radio
r (la porción y dirección dibujada depende del parámetro a, 360
para todo)
A partir de la orientación actual, rota la tortuga a grados en sentido contrario a las manecillas del reloj
Levanta el lápiz (cualquier movimiento no dibujará su recorrido)
Baja el lápiz (cualquier movimiento dibujará su recorrido)
Reporta el valor de la posición de la tortuga
Reporta el valor de la orientación de la tortuga
Deshace la última acción ejecutada por la tortuga
Borra todo lo dibujado por la tortuga (no mueve la tortuga)
Lleva la tortuga al centro del mundo (no borra lo dibujado)
Reinicia todo el sistema y posiciona la tortuga en la posición x = 0
y y = 0, con orientación θ = 0
FT
Operación
forward(u)
circle(r,a)
DR
A
Cuadro 3.1: Operaciones básicas en el Mundo de la Tortuga
Figura 3.3: Estado inicial y final para dibujar una persona
33
3 Noción de Estado
# Dibuja la cabeza
turtle.pendown()
turtle.circle(50,360)
# Dibuja el cuerpo
turtle.left(270)
turtle.forward(200)
FT
# Se posiciona para dibujar la cabeza
turtle.penup()
turtle.left(90)
turtle.forward(100)
turtle.left(270)
# Dibuja la pierna izquierda
turtle.left(45)
turtle.forward(100)
DR
A
# Se posiciona para dibujar la pierna derecha
turtle.penup()
turtle.left(180)
turtle.forward(100)
turtle.left(90)
# Dibuja la pierna derecha
turtle.pendown()
turtle.forward(100)
# Se posiciona para dibujar los brazos
turtle.penup()
turtle.left(180)
turtle.forward(100)
turtle.left(45)
turtle.forward(150)
turtle.left(90)
turtle.forward(75)
turtle.left(180)
# Dibuja los dos brazos
turtle.pendown()
turtle.forward(150)
Algoritmo 3.1: Dibuja una persona
Cuando se tiene un sistema cuyo estado actual no es el deseado, se dice que se tiene un
34
3.1 Estado
problema. La solución a un problema es una serie de pasos (ejecuciones de operaciones)
que llevan del estado en que están las cosas en el sistema al estado que se desean, es decir,
un algoritmo.
# Se cambia el color del lápiz
turtle.pencolor("red")
DR
A
# Sale del laberinto
turtle.forward(350)
turtle.left(90)
turtle.forward(150)
turtle.left(90)
turtle.forward(50)
turtle.left(90)
turtle.forward(100)
turtle.left(270)
turtle.forward(200)
turtle.left(270)
turtle.forward(150)
turtle.left(270)
turtle.forward(100)
turtle.left(90)
turtle.forward(50)
turtle.left(90)
turtle.forward(150)
turtle.left(270)
turtle.forward(100)
turtle.left(270)
turtle.forward(300)
turtle.left(90)
turtle.forward(50)
FT
Ejemplo 3.2
La tortuga Junior se encuentra atrapada en el laberinto de la figura 3.4. Resuelva el problema de sacar a Junior del laberinto. Inicialmente la tortuga se encuentra en la posición
(-175,175). Los lados del cuadrado externo del laberinto tienen una longitud de 400 pixeles,
la esquina superior izquierda está en (-200,200) y el ancho de los pasadizos del laberinto es
de 50 pixeles.
Problema
Algoritmo 3.2: Sale del laberinto cuadrado
El algoritmo 3.2 muestra los pasos para resolver el problema. Si se aplica dicho algoritmo
en el estado inicial del problema, se obtendrá como resultado el estado en la figura 3.5.
? ? ?
35
FT
3 Noción de Estado
DR
A
Figura 3.4: Problema de sacar la tortuga del laberinto
Figura 3.5: Solución al problema de sacar la tortuga del laberinto
36
3.2 Ejercicios
El algoritmo 3.2 usa una nueva operación llamada pencolor(c) para cambiar el color
del lápiz con el cual dibuja la tortuga. Otras operaciones similares para hacer más vistoso
el mundo están en la tabla 3.2.
fillcolor(c)
begin fill()
end fill()
bgcolor(c)
Acción
Cambia el color del lápiz a c (c debe ser una cadena de texto, e.g.
”red”, ”orange”, ”green”)
Cambia el color de rellenado de las figuras a c (c debe ser una
cadena de texto, e.g. ”red”, ”orange”, ”green”)
Las figuras cerradas que dibuje la tortuga serán rellenas con el
color definido en la operación fillcolor(c). Para que las figuras
se coloreen, se debe llamar a end fill() después de dibujar
Termina el proceso de rellenar las figuras cerradas
Cambia el color de fondo de la ventana a c (c debe ser una cadena
de texto, e.g. ”red”, ”orange”, ”green”)
FT
Operación
pencolor(c)
Cuadro 3.2: Operaciones de colores en el Mundo de la Tortuga
Ejercicios
DR
A
3.2.
3.1 Haga un algoritmo que ponga a la tortuga a dibujar su nombre y apellido.
3.2 Mejore el algoritmo de dibujar una persona. Agrégue los ojos, la nariz, la boca,
camiseta, pantalón, manos y pies. Use colores.
3.3 Resuelva el problema de llevar a la tortuga Junior (tortuga negra) donde su mamá (tortuga roja). El laberinto del problema se puede ver en la figura 3.6.
La tortuga mamá se encuentra en el centro del mundo (0,0) mientras que Junior se
encuentra en (-150,180). Los semi-cı́rculos que rodean a la mamá son concéntricos y
si se enumeraran desde el más interno hasta el más externo, el semi-cı́rculo 1 tiene
un radio de 33 pixeles, el semi-cı́rculo 2 tiene un radio de 60 pixeles, el semi-cı́rculo
3 tiene un radio de 90 pixeles, el semi-cı́rculo 4 tiene un radio de 120 pixeles y el
semi-cı́rculo 5 tiene un radio de 150 pixeles.
3.4 Desarrolle un algoritmo para que la tortuga construya una sopa de letras.
37
DR
A
FT
3 Noción de Estado
Figura 3.6: Problema de llevar la tortuga donde su mamá
38
4.1.
Abstracción de Control
FT
4 Noción de Abstracción
DR
A
Normalmente, a medida que se van resolviendo problemas más complicados, la cantidad
de operaciones básicas que deben realizarse y la cantidad de datos a procesar es mayor.
Adicionalmente, muchas veces el algoritmo que resulta no es lo suficientemente intuitivo
como para entenderlo fácilmente, por el contrario, se puede ver como una lista de comandos cuyo propósito es indefinido. Por ejemplo, si tomamos el algoritmo 3.1 (ejemplo 3.1),
eliminamos los comentarios y omitimos el propósito del algoritmo, una persona solo con
mirar el código tendrı́a dificultad en encontrar su objetivo. Esto se debe a que el nivel de
abstracción del algoritmo es bajo.
Abstracción es el proceso en el que datos y algoritmos son agrupados de acuerdo a una
semántica particular, de manera que se reduzcan los detalles. El proceso de abstracción
puede aplicarse a operaciones o a datos. En este capı́tulo veremos la abstracción que involucra algoritmos, llamada abstracción de control. En el capı́tulo 7 se verá la abstracción de
datos.
El nivel de abstracción de un sistema define la cantidad de detalles a tener en cuenta al
realizar el modelo computacional del sistema. El mundo de la tortuga, por ejemplo, tiene un
alto nivel de abstracción ya que las operaciones básicas son claras en cuanto a su propósito
y el programador sabe que si ejecuta una operación, el resultado se verá gráficamente, no
importa el computador en el que se ejecute. Si el nivel de abstracción del mundo de la
tortuga fuera bajo, el programador tendrı́a que lidiar con operaciones del procesador y la
tarjeta de video del computador en el que quiera ejecutar el programa, es decir, rutinas
propias de la máquina. En el ejemplo 4.1 se muestra cómo aumentar el nivel de abstracción
del algoritmo 3.1.
Ejemplo 4.1
Si queremos dibujar una persona, podemos dividir el dibujo en las partes del cuerpo: cabeza,
tronco, y extremidades, y definimos cada una de estas partes como una operación diferente.
Las nuevas operaciones para dibujar las extremidades, el tronco y la cabeza están definidas en los algoritmos 4.1, 4.2 y 4.3.
39
Abstracción
4 Noción de Abstracción
FT
def dibujarExtremidades():
"Dibuja las extremidades de una persona"
# Dibuja la pierna izquierda
turtle.left(45)
turtle.forward(100)
# Se posiciona para dibujar la pierna derecha
turtle.penup()
turtle.left(180)
turtle.forward(100)
turtle.left(90)
# Dibuja la pierna derecha
turtle.pendown()
turtle.forward(100)
DR
A
# Se posiciona para dibujar los brazos
turtle.penup()
turtle.left(180)
turtle.forward(100)
turtle.left(45)
turtle.forward(150)
turtle.left(90)
turtle.forward(75)
turtle.left(180)
# Dibuja los dos brazos
turtle.pendown()
turtle.forward(150)
Algoritmo 4.1: Dibuja las extremidades de una persona
def dibujarTronco():
"Dibuja el tronco de una persona"
# Dibuja el cuerpo
turtle.left(270)
turtle.forward(200)
Algoritmo 4.2: Dibuja el tronco de una persona
40
4.1 Abstracción de Control
# Dibuja la cabeza
turtle.pendown()
turtle.circle(50,360)
FT
def dibujarCabeza():
"Dibuja la cabeza de una persona"
# Se posiciona para dibujar la cabeza
turtle.penup()
turtle.left(90)
turtle.forward(100)
turtle.left(270)
Algoritmo 4.3: Dibuja la cabeza de una persona
El algoritmo para dibujar una persona se reduce ahora a cargar y aplicar las operaciones
recién creadas, como en el algoritmo 4.4. Note que si a dicho algoritmo le quitamos los
comentarios, aún ası́ el usuario que lea el algoritmo tiene una idea de cuál es su propósito
solo con echarle un vistazo.
DR
A
# Dibuja la cabeza
dibujarCabeza()
# Dibuja el cuerpo
dibujarTronco()
# Dibuja las extremidades
dibujarExtremidades()
Algoritmo 4.4: Dibuja completamente una persona
? ? ?
En los algoritmos 4.3, 4.2, y 4.1 se han definido las operaciones dibujarExtremidades(),
dibujarTronco() y dibujarCabeza(). La definición de una operación especifica un identificador (que va a ser usado para aplicar la operación) y el cuerpo de dicha operación. La
especificación del cuerpo de una operación es denominada implementación de la operación.
En el algoritmo 4.4 se usan las operaciones previamente definidas. Cuando una operación
es usada de esta manera, se dice que se hace una aplicación de la operación. Aplicar una
operación es, finalmente, hacer el llamado a la operación.
Ejemplo 4.2
Supongamos que queremos dibujar un conjunto de casas. La manera mas sencilla es crear
41
Definición
Implementación
Aplicación
4 Noción de Abstracción
def dibujarCasa():
"Dibuja una casa"
# Dibuja la pared
turtle.pendown()
turtle.left(270)
turtle.forward(100)
turtle.left(270)
turtle.forward(100)
turtle.left(270)
turtle.forward(100)
turtle.left(270)
turtle.forward(100)
DR
A
# Dibuja el techo
turtle.left(135)
turtle.forward(70.7)
turtle.left(90)
turtle.forward(70.7))
FT
una operación para dibujar una sola casa y luego ejecutar dicha operación tantas veces
como número de casas se quiera. El algoritmo 4.5 define una operación para dibujar una
casa.
# Dibuja la puerta y termina
turtle.penup()
turtle.left(45)
turtle.forward(100)
turtle.left(90)
turtle.forward(40)
turtle.left(90)
turtle.pendown()
turtle.forward(30)
turtle.left(270)
turtle.forward(20)
turtle.left(270)
turtle.forward(30)
turtle.left(90)
turtle.penup()
turtle.forward(40)
turtle.left(90)
turtle.forward(100)
Algoritmo 4.5: Dibuja una casa
Luego ejecutamos la operación para dibujar una casa varias veces, como en el algoritmo
4.6, en el cual se dibujan cuatro casas.
42
4.1 Abstracción de Control
FT
# Dibuja cuatro casas
dibujarCasa()
dibujarCasa()
dibujarCasa()
dibujarCasa()
Algoritmo 4.6: Dibuja cuatro casas
? ? ?
DR
A
Podemos ver que el nivel de abstracción del algoritmo 4.5 puede aumentarse separando
las partes de la casa y definiéndolas como operaciones separadas.
Por otra parte, el lector que pruebe el algoritmo 4.6 puede darse cuenta que el resultado
que se obtiene no es el esperado. La figura 4.1 muestra lo que la tortuga dibuja después de
aplicado el algoritmo.
Figura 4.1: Resultado de aplicar el algoritmo para dibujar una casa cuatro veces
Es claro que la tortuga dibuja cuatro casas, pero no es el resultado esperado; el resultado
que se quisiera es el que se muestra en la figura 4.2.
43
FT
4 Noción de Abstracción
DR
A
Figura 4.2: Resultado esperado de aplicar el algoritmo para dibujar una casa cuatro veces
Parámetro
Argumento
El problema que ocurre es que la posición y la orientación inicial de la tortuga en cada
ejecución de la operación no es la correcta. Por lo tanto, debemos darle a la operación estos
datos para que la tortuga pueda dibujar las casas como deseamos. En el algoritmo 4.7 se
define la operación con la posición en x y en y como datos de entrada.
Cuando se definen operaciones, a los datos de entrada de ellas se les llama parámetros.
Un parámetro de una operación es entonces, un tipo especial de variable que provee datos
necesarios que pueden ser usados en la operación.
Con la nueva definición de la operación para dibujar una casa, se puede hacer un algoritmo más adecuado para dibujar cuatro casas y que, de hecho, queden como en la figura
4.2. El resultado es el algoritmo 4.8.
Los valores que se proveen como datos de entrada a la ejecución de una operación son
llamados los argumentos de la operación. En el algoritmo 4.8, por ejemplo, −100 y 0 son
los argumentos de la primera aplicación de la operación dibujarCasa().
En el algoritmo 4.7 se incorporan nuevas operaciones del mundo de la tortuga. Estas
operaciones sirven para posicionar y orientar la tortuga en un lugar particular del mundo
sin necesidad de llevarla hasta allá con left() y forward(). Estas y otras operaciones
están en el cuadro 4.1.
44
4.1 Abstracción de Control
# Dibuja la pared
turtle.pendown()
turtle.left(270)
turtle.forward(100)
turtle.left(270)
turtle.forward(100)
turtle.left(270)
turtle.forward(100)
turtle.left(270)
turtle.forward(100)
DR
A
# Dibuja el techo
turtle.left(135)
turtle.forward(70.7)
turtle.left(90)
turtle.forward(70.7))
FT
def dibujarCasa(x,y):
"Dibuja una casa dada una posicion"
# Se posiciona donde quiere dibujar la casa y orienta a la
# tortuga en 0 grados
turtle.penup()
turtle.setx(x)
turtle.sety(y)
turtle.seth(0)
# Dibuja la puerta y termina
turtle.penup()
turtle.left(45)
turtle.forward(100)
turtle.left(90)
turtle.forward(40)
turtle.left(90)
turtle.pendown()
turtle.forward(30)
turtle.left(270)
turtle.forward(20)
turtle.left(270)
turtle.forward(30)
turtle.left(90)
turtle.penup()
turtle.forward(40)
turtle.left(90)
turtle.forward(100)
Algoritmo 4.7: Dibuja una casa con posición
45
4 Noción de Abstracción
FT
# Dibuja cuatro casas especificando su posicion
dibujarCasa(-100,0)
dibujarCasa(0,0)
dibujarCasa(100,0)
dibujarCasa(200,0)
Algoritmo 4.8: Dibuja cuatro casas especificando las posiciones
Operación
goto(x,y)
setx(x)
sety(y)
DR
A
seth(h)
xcor()
ycor()
Acción
Traslada la tortuga a la posición x = x, y = y. La orientación
permanece igual
Traslada la tortuga a la coordenada x = x sin cambiar la coordenada y. La orientación permanece igual
Traslada la tortuga a la coordenada y = y sin cambiar la coordenada x. La orientación permanece igual
Orienta la tortuga al ángulo a = h
Reporta el valor de la posición de la tortuga en el eje x
Reporta el valor de la posición de la tortuga en el eje y
Cuadro 4.1: Operaciones de posicionamiento y orientación en el Mundo de la Tortuga
Ejemplo 4.3
Ahora queremos que la tortuga escriba la letra ’A’ pero en diferentes escalas, es decir, con
un tamaño que depende de un valor de entrada. Para esto se necesita definir una operación
que tenga un parámetro escala cuyo dominio de valores se encuentre entre 1 y 100. Este
parámetro será usado para determinar las longitudes de las lı́neas que componen la letra
’A’ y los ángulos que debe usar la tortuga para hacer el dibujo. El algoritmo 4.9 resuelve
este problema.
Se asume que la letra a una escala 100 ocupa la mayor parte de la ventana y el dibujo de
la letra más pequeña tiene una escala 1. Como la ventana es de 500 × 500 pixeles, entonces
la tortuga se moverá inicialmente a una posición determinada por la escala y un factor de
−2,3. Ası́, si la escala es 100, la posición inicial será (−230, −230), mientras que si la escala
es 1, la posición será (−2,3, −2,3).
Como puede verse para hallar las longitudes de las lı́neas diagonales se usa (de nuevo) el
teorema de Pitágoras, y para hallar el ángulo que debe tomar la tortuga para dibujar las
diagonales se usa la función trigonométrica arcoseno. Estas operaciones necesarias en este
problema (y en algunos siguientes) hacen parte de un sistema matemático; algunas de las
46
4.1 Abstracción de Control
operaciones más usadas de este sistema se encuentran en el cuadro 4.2.
FT
def letraAescala(escala):
"Dibuja la letra 'A' con una escala dada"
# Se posiciona para dibujar
turtle.penup()
turtle.setx(-2.3*escala)
turtle.sety(-2.3*escala)
turtle.seth(0)
# Calcula los valores necesarios para la letra, a partir de
# la escala
longitud = math.sqrt((2.3*escala * 2.3*escala) + \
(4.6*escala * 4.6*escala))
angulo = (math.asin(4.6*escala/longitud)*360)/(2*math.pi)
# Dibuja la primera diagonal
turtle.pendown()
turtle.left(angulo)
turtle.forward(longitud)
DR
A
# Dibuja la segunda diagonal
turtle.seth(0)
turtle.left(360-angulo)
turtle.forward(longitud)
# Se posiciona para dibujar la linea intermedia
turtle.left(180)
turtle.penup()
turtle.forward(longitud/3)
# Dibuja la linea intermedia
turtle.seth(180)
turtle.pendown()
linea = turtle.xcor()*2
turtle.forward(linea)
# Mueve la tortuga a una posicion que permita ver el resultado
turtle.penup()
turtle.goto(-235,235)
turtle.seth(0)
Algoritmo 4.9: Dibuja la letra A
? ? ?
47
4 Noción de Abstracción
Operación
pow(x,y)
sqrt(x)
log(x,b)
sin(v)
cos(v)
tan(v)
asin(v)
acos(v)
atan(v)
degrees(a)
radians(a)
Acción
Retorna
Retorna
Retorna
Retorna
Retorna
Retorna
Retorna
Retorna
Retorna
Retorna
Retorna
Constante
pi
e
Valor
El valor matemático π = 3,141592...
El valor matemático e = 2,718281...
x elevado a la y
la raiz cuadrada de x
el logaritmo base b de x
el seno de a, en radianes
el coseno de a, en radianes
la tangente de a, en radianes
el arcoseno de a, en radianes
el arcocoseno de a, en radianes
la arcotangente de a, en radianes
la conversión del ángulo a de radianes a grados
la conversión del ángulo a de grados a radianes
DR
A
Alcance
FT
Declaración
El lector puede notar que en el algoritmo 4.9 se han usado unas variables longitud,
angulo y linea. Estas variables se dice que son locales ya que son declaradas (usadas por
primera vez o por lo menos anunciadas de que existen) dentro del contexto de la operación
definida. Por fuera del contexto (en el caso de las variables longitud, angulo y linea, por
fuera de la operación letraAescala()), dichas variables no son visibles o accesibles. Por
otro lado, las variables globales son aquellas que pueden ser usadas en cualquier contexto,
es decir, en cualquier parte del código del modelo computacional. Por lo tanto, el contexto
en el que son declaradas las variables define su alcance, esto es, la visibilidad o accesibilidad
de las variables en diferentes partes del modelo computacional.
Cuadro 4.2: Operaciones y constantes clásicas de un sistema matemático
Función
Los valores de las variables locales longitud, ángulo y linea son obtenidos al aplicar las
operaciones sqrt(), asin() y xcor(), respectivamente. Estas operaciones en su definición
han hecho aplicaciones de otras operaciones y cálculos internos, y al final ellas (sqrt(),
asin() y xcor()) reportan un valor, el cual es retornado a la operación donde fueron
aplicadas (en este caso letraAescala()) y se asignan a las variables longitud, angulo y
linea. Cuando una operación reporta un valor que es retornado al final de su definición,
a dicha operación se le denomina función.
Ejemplo 4.4
El curso de Introducción a la programación se evalúa con tres exámenes parciales, tareas
48
4.1 Abstracción de Control
y un proyecto. El cuadro 4.3 muestra los porcentajes que tienen estos elementos en la nota
final del curso.
Porcentaje
25 %
20 %
20 %
15 %
20 %
FT
Evaluación
Examen Parcial 1
Examen Parcial 2
Examen Parcial 3
Tareas
Proyecto
Cuadro 4.3: Porcentaje de notas de un curso Introducción a la Programación
Si quisiéramos que la tortuga escribiera la nota final del curso dados los datos de las
evaluaciones, primero tenemos que hacer la función que retorne la nota final y luego hacer
que la tortuga escriba este valor reportado. La función está definida en el algoritmo 4.10.
DR
A
def notaFinal(p1, p2, p3, t, pry):
"Funcion que haya la nota final del curso"
nota = (p1*0.25) + (p2*0.2) + (p3*0.2) + (t*0.15) + (pry*0.2)
return nota
Algoritmo 4.10: Retorna la nota final del curso
Esta función puede usarse entonces en un algoritmo que haga dibujar a la tortuga la
nota final, como el algoritmo 4.11.
def escribirNotaFinal():
"Escribe la nota final de un curso"
# Halla el dia del domingo de Pascua
valor = notaFinal(4.5, 4.0, 5.0, 4.0, 5.0)
# Escribe la nota y termina
turtle.write(valor, False, align="center", \
font=("Arial",32,"normal"))
turtle.penup()
turtle.goto(-235,235)
Algoritmo 4.11: Escribe la nota final del curso
? ? ?
En el algoritmo 4.11 se usa una operación para escritura. Esta operación está descrita
49
4 Noción de Abstracción
en el cuadro 4.4.
Acción
Escribe en la posición actual el texto t. El parámetro m es un
valor lógico (True o False) que especifica si la tortuga se desplazará cuando escriba el texto. El parámetro a define la alineación
del texto (“left”, “center”, o “right”). El parámetro f es una estructura que describe la fuente del texto (esta estructura se codifica entre paréntesis con los datos separados por comas, ası́:
(nombre, tamaño, tipo), e.g. (“Arial”,18,“italic”))
FT
Operación
write(t,m,a,f)
Cuadro 4.4: Operación de escritura en el Mundo de la Tortuga
Procedimiento
DR
A
Composición
Las operaciones que no reportan un valor y, por lo tanto, no es retornado a la operación
donde se aplica se les llama procedimientos. Todas las operaciones que se han definido hasta
el momento, excepto notaFinal(), son procedimientos.
Las funciones, dado que retornan un valor que puede asignarse a una variable y, por
lo tanto, puede usarse en otras operaciones, pueden aplicarse como argumento de otra
aplicación. Este proceso es conocido como composición de funciones. El ejemplo 4.5 muestra
un algoritmo con composición de funciones.
Ejemplo 4.5
Supongamos que queremos construir la función que retorna la longitud de la hipotenusa
de un triángulo rectángulo, dadas las longitudes de los dos catetos (esto nos sirve de ayuda
en varios ejemplos vistos). Para resolver este problema se usa el teorema de pitágoras. El
algoritmo 4.12 muestra su uso de dos maneras diferentes.
def longitudHipotenusa1(cateto1, cateto2):
"Retorna la longitud de la hipotenusa de un triangulo rectangulo"
valor1 = math.pow(cateto1,2)
valor2 = math.pow(cateto2,2)
hipotenusa = math.sqrt(valor1+valor2)
return hipotenusa
def longitudHipotenusa2(cateto1, cateto2):
"Retorna la longitud de la hipotenusa de un triangulo rectangulo"
return math.sqrt(math.pow(cateto1,2)+math.pow(cateto2,2))
Algoritmo 4.12: Retorna la longitud de la hipotenusa de un triángulo rectángulo
Las dos funciones retornan exactamente lo mismo. La primera función declara dos variables locales que contendrán el valor resultado de elevar al cuadrado las longitudes de
50
4.1 Abstracción de Control
FT
los dos catetos y luego aplica la función de raı́z cuadrada con la suma de las dos variables
como argumento. El resultado de la función raı́z cuadrada se asigna a una última variable
local, cuyo valor será retornado por la función.
La segunda función se ahorra la declaración de las variables aplicando directamente la
función de raı́z cuadrada con el resultado de la función de elevar al cuadrado los catetos y
sumarlos, es decir, componiendo las funciones.
? ? ?
DR
A
Ejemplo 4.6
A principio de cada año una de las preguntas más frecuentes entre nosotros es ¿en qué fecha
cae Semana Santa?
La tortuga Sabelotodo encontró que una fórmula para calcular la fecha del Domingo de
Pascua en los años 1982–2048, inclusive, es ası́1 : sea a = ano %19, b = ano %4, c = ano %7,
d = (19a + 24) %30, e = (2b + 4c + 6d + 5) %7, entonces el dı́a del Domingo de Pascua es
Marzo 22 + d + e.
Esta fórmula la podemos usar para crear la función Pascua. Esta función tiene como
parámetro un año y retorna el dı́a del Domingo de Pascua de ese año. El algoritmo 4.13
muestra la función.
def Pascua(ano):
"Funcion que halla el día del domingo de pascua"
a = ano%19
b = ano%4
c = ano%7
d = (19*a + 24)%30
e = (2*b + 4*c + 6*d + 5)%7
dia = 22 + d + e
return dia
Algoritmo 4.13: Retorna el dı́a del Domingo de Pascua
Usando esta función, podemos poner a la tortuga a escribir la fecha del Domingo de
Pascua (o toda la Semana Santa) con un algoritmo similar al algoritmo 4.11.
? ? ?
Si el lector prueba el algoritmo 4.13, aplicándolo con diferentes años como argumento,
podrá notar que en algunas ocasiones se obtendrán resultados inconsistentes cronológicamente. Por ejemplo, la función Pascua con un argumento 2000 retorna 54. Sin embargo no
1
La operación módulo ’ %’ halla el residuo de la división entera entre dos números.
51
4 Noción de Abstracción
4.2.
Ejercicios
FT
existe la fecha Marzo 54 de 2000, Marzo tiene solo 31 dı́as y el dı́a siguiente es Abril 1. De
esta manera, es necesario considerar los casos para los que la fecha está en Marzo y aquellos
donde la fecha está en Abril. La estructura de control para tener dichas consideraciones se
verá en el capı́tulo 5.
4.1 Mejore los procedimientos 4.1, 4.2 y 4.3, creándoles parámetros que especifiquen las
posiciones donde van a ser dibujados.
4.2 Baje el nivel de abstracción del dibujo de una persona, desarrollando los procedimientos y funciones para dibujar todas partes del cuerpo humano. Por ejemplo, en vez de
dibujarCabeza(), puede construir las operaciones dibujarOjos(), dibujarNariz(),
dibujarBoca(), dibujarOrejas(), etc., con sus respectivos parámetros de posición y
otros parámetros que se deseen (e.g. dibujarOjos() puede tener además un parámetro que especifique el color de los ojos).
DR
A
4.3 Desarrolle un procedimiento para que la tortuga escriba su nombre en diferentes
escalas.
4.4 Se quiere que la tortuga dibuje una pequeña ciudad con un carro en ella. Cree entonces
un procedimiento que lo haga y que permita dibujar el carro en diferentes calles de
ella. Adicionalmente el procedimiento debe tener la capacidad de hacer zoom en
cualquier parte de la pequeña ciudad (piense en un Google Maps – http://maps.
google.com/ – muy muy sencillo).
4.5 Escriba una función con dos parámetros correspondientes a la base y la altura de un
triángulo isósceles y haga que la tortuga dibuje el triángulo. La función debe retornar
el valor del área del triángulo.
4.6 Desarrolle un algoritmo para que la tortuga construya un sudoku y luego defina las
operaciones para resolver cualquier sudoku.
52
5.1.
Condición
FT
5 Noción de Condición
Cuando el estado en que se encuentra un sistema se desconoce, no podemos garantizar
que un algoritmo desarrollado llegue al estado deseado. Lo anterior debido a que no tenemos
forma de saber qué operaciones deben realizarse a partir de dicho estado desconocido para
lograr llegar al estado final. Sin embargo si consideráramos todos los casos posibles, entonces
sı́ garantizarı́amos llegar al estado final. Para diferenciar un caso de otro es necesario que
el estado del sistema cumpla una condición.
Una condición es:
una relación lógica entre variables, ó
DR
A
una función que retorna un valor de tipo Booleano.
Una relación lógica entre variables se construye utilizando operadores de relación. Los
operadores de relación entre variables son ==, <, >, <=, >=, ! =, <>. Por ejemplo, si
tenemos la siguiente relación:
x >= 5
esta relación es verdadera en el caso en que la variable x sea asignada con valores mayores
o iguales a 5. De lo contrario la relación es falsa. La semántica de los operadores de relación
es como sigue:
el operador < significa menor que.
el operador > significa mayor que.
el operador == significa igual que.
el operador <= significa menor o igual que.
el operador >= significa mayor o igual que.
los operadores ! = y <> significan distinto de.
53
Condición
5 Noción de Condición
Operación
p and q
Acción
Retorna True cuando los valores de ambas variables p y q son
True. De lo contrario retorna False. Esto se ve mas claramente
en la siguiente tabla de verdad:
p or q
q
True
False
True
False
Retorna True cuando el valor de cualquiera de las dos variables
p y q es True. De lo contrario retorna False. Esto se ve mas
claramente en la siguiente tabla de verdad:
q
True
False
True
False
DR
A
p
True
True
False
False
not p
p or q
True
True
True
False
Retorna True cuando el valor de la variable p es False. De lo
contrario retorna False. Esto se ve mas claramente en la siguiente
tabla de verdad:
p
True
False
Constante
True
False
p and q
True
False
False
False
FT
p
True
True
False
False
not p
False
True
Valor
El valor Booleano 1
El valor Booleano 0
Cuadro 5.1: Operaciones y constantes clásicas de un sistema Booleano
De otro lado, la implementación de funciones que retornan valores de tipo Booleano se
logra combinando constantes lógicas (True y False), variables lógicas (i.e. con tipo de dato
54
5.1 Condición
Booleano) y operaciones lógicas. Las operaciones lógicas son aquellas que al ser aplicadas
producen un valor Booleano. Algunas de estas operaciones se pueden ver en el cuadro 5.1.
Un condicional es una sentencia que evalúa una condición y de acuerdo al resultado de
dicha evaluación, ejecuta o no, un conjunto de operaciones.
DR
A
FT
Ejemplo 5.1
Supongamos que la tortuga Junior tiene dos opciones para divertirse esta noche. Una opción
es ir a una discoteca mientras que la otra es ir a comer helado. La decisión depende de la
edad que tenga Junior dado que para entrar a las discotecas se requiere tener mas de 18
años.
La figura 5.1 muestra el estado inicial del problema, con Junior al frente de ambos
edificios.
Condicional
Figura 5.1: Estado inicial del problema de mayorı́a de edad
El algoritmo 5.1 desarrolla la función esMayorDeEdad() la cual recibe como parámetro un
número natural que representa la edad y retorna True o False dependiendo si el argumento
pasado a la función en su aplicación es mayor o igual a 18, o no.
Para hacer que Junior vaya a la discoteca, debemos entonces aplicar la función
esMayorDeEdad() del algoritmo 5.1 con un número mayor o igual a 18 como argumento.
Esto hace que la función retorne True y el estado final del sistema sea el de la figura 5.2a.
Por otro lado, si aplicamos la función con un número menor a 18, ella retornará False (ya
que la condición no se cumple (edad >= 18), la variable mayor no se modifica y se queda
55
5 Noción de Condición
con el valor que se le dio en su declaración, es decir, False) y el estado final del sistema
será el de la figura 5.2b.
FT
def esMayorDeEdad(edad):
"Funcion que retorna si es mayor de edad o no"
mayor = False
if edad >= 18:
mayor = True
return mayor
DR
A
Algoritmo 5.1: Retorna si un número es mayor o igual a 18
(a) Solución 1
(b) Solución 2
Figura 5.2: Los dos posibles casos del problema de mayorı́a de edad
Flujo de Ejecución
? ? ?
En el ejemplo 5.1 puede notarse que en algunos casos se ejecutan unas operaciones y
en otros se ejecutan otras operaciones. El orden de ejecución de las operaciones de un
programa determina el flujo de ejecución del programa. La figura 5.3 da una explicación
gráfica del flujo de la función esMayorDeEdad(). La asignación mayor = False siempre se
56
5.1 Condición
FT
ejecuta. La condición edad >= 18 es evaluada y de acuerdo al resultado se puede ir por
uno de dos caminos: si el resultado de la condición es True entonces se ejecuta la asignación
mayor = True y luego se retorna la variable mayor (es decir se retorna True); si el resultado
de la condición es False entonces simplemente se retorna la variable mayor, que en este
caso tiene asignado el valor original False.
edad
mayor = False
¿edad >= 18?
Cierto
DR
A
mayor = True
Falso
return mayor
Figura 5.3: Flujo de ejecución de la función esMayorDeEdad()
Ejemplo 5.2
Supongamos que la tortuga Junior ha dibujado un tablero de tiro al blanco para jugar un
rato. El tablero que ha dibujado se muestra en la figura 5.4.
Como puede apreciarse, un tablero de tiro al blanco consiste en un número fijo de circunferencias concéntricas separadas por una distancia usualmente constante. En este caso
particular, el tablero tiene ocho circunferencias concéntricas cada una separada 25 unidades
de la siguiente. La circunferencia más pequeña (negra) tiene un radio de 25 unidades.
El juego consiste en disparar al tablero y de acuerdo al lugar donde ocurrió el disparo,
se obtiene un puntaje. Este puntaje es acumulado hasta que se acaben los disparos. El
jugador que más puntaje obtenga al final será el ganador.
57
FT
5 Noción de Condición
DR
A
Figura 5.4: Tablero de tiro al blanco
Lo primero que debemos hacer es construir una función que, dado un disparo, retorne el
puntaje correspondiente. Un disparo se puede ver como una posición en el mundo, es decir,
una posición en el eje x y una posición en el eje y. De allı́ que si hallamos la distancia desde
ese punto hasta el origen (0,0), podrı́amos saber entre qué par de cı́rculos cayó el disparo y,
por lo tanto, saber el puntaje asociado. Entonces la distancia podemos conocerla aplicando
una de las funciones para hallar la hipotenusa del ejemplo 4.5. Luego comparamos el valor
obtenido en la aplicación con cada una de las distancias de las circunferencias y de esta
manera conocemos el puntaje. El algoritmo 5.2 muestra la función.
Vemos que si se aplica esta función con un disparo
en la posición (100,100), el puntaje
√
obtenido es 300 ya que la distancia calculada ( 1002 + 1002 = 141,42) se encuentra entre
125 y 150. Podemos notar además que si se calcula una distancia mayor a 200, el puntaje
retornado es cero; de allı́ que se puede asumir que el disparo no le pegó al tablero.
Ahora hacemos el procedimiento para simular un juego. Para realizar la simulación usamos un sistema de números aleatorios. Este sistema nos permite asumir disparos al azar,
es decir, no tenemos que inventarnos unos números y cada vez que ejecutemos la simulación obtendremos disparos diferentes (un sistema inicial desconocido). Las operaciones del
sistema de números aleatorios se encuentra en el cuadro 5.2.
El procedimiento para la simulación se encuentra en el algoritmo 5.3. Primero se hallan
los disparos utilizando la función randint(), luego se hallan los puntajes y con ellos se
58
5.1 Condición
randint(a,b)
Acción
Retorna el siguiente número real aleatorio en el rango [0,0, 1,0)
Retorna número aleatorio en la lista de números entre i y f con
intervalos de p. Por ejemplo, si queremos un número aleatorio par
entre 0 y 10, le enviamos los argumentos a la función: i=0, f=10,
p = 2 (la lista de números entre 0 y 10 con intervalos de 2 es
{0, 2, 4, 6, 8, 10})
Retorna un número entero aleatorio n de manera que a ≤ n ≤ b
FT
Operación
random()
randrange(i,f,p)
Cuadro 5.2: Operaciones básicas de un sistema de números aleatorios
encuentra el ganador.
DR
A
def puntajeXdisparo(x,y):
"Funcion que retorna el puntaje dado el disparo"
distancia = longitudHipotenusa2(x,y)
puntaje = 0
if distancia <= 25:
puntaje = 1000
if distancia > 25 and distancia <= 50:
puntaje = 800
if distancia > 50 and distancia <= 75:
puntaje = 600
if distancia > 75 and distancia <= 100:
puntaje = 500
if distancia > 100 and distancia <= 125:
puntaje = 400
if distancia > 125 and distancia <= 150:
puntaje = 300
if distancia > 150 and distancia <= 175:
puntaje = 200
if distancia > 175 and distancia <= 200:
puntaje = 100
return puntaje
Algoritmo 5.2: Retorna el puntaje dado un disparo
En el algoritmo 5.3 pueden notarse algunas cosas. El juego consiste en tres disparos que
se representan con seis variables (la posición en x y y de cada disparo). Con estas seis
variables se calculan los tres puntales obtenidos en los tres disparos, que se suman para
tener el puntaje total. Lo anterior se realiza para los dos jugadores. Puede verse que todas
59
5 Noción de Condición
FT
las variables (excepto las de puntaje total) son asignadas dos veces, esto está bien ya que
una vez se usan las variables para realizar los cálculos, su valor deja de ser necesario. Por
otro lado, cada posición de un disparo se tiene después de aplicar la función randint() con
argumentos 0 y 250; como la distancia máxima para obtener un punto es 200, este valor
(250) permite simular un jugador que realiza un tiro malo.
def tiroAlBlanco():
"Procedimiento que simula un juego de tiro al blanco"
# Jugador 1
disparo1x = random.randint(0,250)
disparo1y = random.randint(0,250)
disparo2x = random.randint(0,250)
disparo2y = random.randint(0,250)
disparo3x = random.randint(0,250)
disparo3y = random.randint(0,250)
puntaje1 = puntajeXdisparo(disparo1x,disparo1y)
puntaje2 = puntajeXdisparo(disparo2x,disparo2y)
puntaje3 = puntajeXdisparo(disparo3x,disparo3y)
puntajeTotalJugador1 = puntaje1 + puntaje2 + puntaje3
DR
A
# Jugador 2
disparo1x = random.randint(0,250)
disparo1y = random.randint(0,250)
disparo2x = random.randint(0,250)
disparo2y = random.randint(0,250)
disparo3x = random.randint(0,250)
disparo3y = random.randint(0,250)
puntaje1 = puntajeXdisparo(disparo1x,disparo1y)
puntaje2 = puntajeXdisparo(disparo2x,disparo2y)
puntaje3 = puntajeXdisparo(disparo3x,disparo3y)
puntajeTotalJugador2 = puntaje1 + puntaje2 + puntaje3
# Ganador
if puntajeTotalJugador1 > puntajeTotalJugador2:
turtle.write("El ganador es el jugador 1")
if puntajeTotalJugador1 < puntajeTotalJugador2:
turtle.write("El ganador es el jugador 2")
if puntajeTotalJugador1 == puntajeTotalJugador2:
turtle.write("El juego quedo empatado")
Algoritmo 5.3: Simula un juego de tiro al blanco
? ? ?
En algunas ocasiones solo se tiene una posible condición en el sistema que se está mode-
60
5.1 Condición
lando. Por esto si la condición se cumple entonces el flujo de ejecución del programa va por
un camino, pero si no se cumple el flujo debe ir por otro. En estos casos, se puede hacer uso
del complemento opcional de un condicional (if) llamada la condición por defecto (else).
El ejemplo 5.3 muestra el uso de la condición por defecto.
FT
Ejemplo 5.3
Retomando el ejemplo 4.6, si quisiéramos que la tortuga escribiera la fecha cronológicamente bien (que no escriba Marzo 54 de 2000, por ejemplo) entonces después de aplicar
la función Pascua() debemos tener en cuenta los casos. Si el número retornado es menor
o igual que 31, entonces la tortuga debe escribir la fecha en Marzo, de lo contrario debe
escribir la fecha en Abril.
El algoritmo 5.4 muestra el código para la escritura correcta de la fecha del domingo
de Pascua de cualquier año. Es claro que si el dı́a no es menor o igual a 31 entonces debe
ser mayor a 31 (es la única otra opción), por lo tanto se puede utilizar la condición por
defecto, es decir, no hay necesidad de especificar “if dı́a > 31:”. Adicionalmente, para
escribir la fecha correcta es necesario utilizar unas operaciones para manejo de cadenas de
texto. El cuadro 5.3 describe algunas operaciones básicas de cadenas de texto.
Condición por Defecto
DR
A
def PascuaMejorado(ano):
"Escribe el día del domingo de Pascua de acuerdo a un ano"
# Halla el día del domingo de Pascua
dia = Pascua(ano)
# Si el dia pertenece a Marzo o a Abril
if(dia <= 31):
fecha = "Marzo " + str(dia) + " de " + str(ano)
else:
dia = dia - 31
fecha = "Abril " + str(dia) + " de " + str(ano)
# Escribe la fecha
turtle.write(fecha, False, align="center",
font=("Arial",32,"normal"))
turtle.penup()
turtle.goto(-235,235)
Algoritmo 5.4: Escribe correctamente la fecha del domingo de Pascua
? ? ?
61
5 Noción de Condición
len(w)
find(w,s)
capitalize(w)
w1 + w2
w * n
c in w
Acción
Retorna una cadena de texto que contiene una representación imprimible del objeto w
Retorna el número de caracteres de la cadena w
Retorna la posición más cercana al inicio donde se encuentre la
subcadena s dentro de la cadena w. Si la subcadena no se encuentra
en w, retorna -1
Retorna la cadena w en mayúsculas
Retorna la concatenación de las cadenas w1 y w2
Retorna n copias de la cadena w concatenadas
Retorna un booleano que indica si el caracter c se encuentra en la
cadena w
FT
Operación
str(w)
Cuadro 5.3: Operaciones básicas de un sistema de cadenas de texto
DR
A
Ejemplo 5.4
Supongamos que la tortuga Junior debe ir a un sitio particular de la ciudad. Las opciones
de transporte son: Bus, Taxi ó Carro Particular. Si Junior necesitase llegar antes de 15
minutos y tuviera $30000, entonces Junior escoge mejor irse en Taxi, sin embargo si tuviera
un poco mas de tiempo e igual cantidad de dinero, serı́a indiferente el medio de transporte.
Si tuviera 1 hora o más para llegar a su destino, la tortuga preferirı́a ahorrar el dinero e
irse en Bus. Lo anterior se calcula solo si Junior no tuviera a nadie que lo lleve en Carro
Particular.
Para resolver este problema es necesario tener en cuenta todas las condiciones necesarias
para cada opción de transporte. El algoritmo 5.5 muestra una forma de solucionar el
problema.
La función transporte() tiene tres parámetros: dinero, tiempo y carro. El dinero
y el tiempo son entonces variables de tipo entero, mientras que carro es una variable
de tipo Booleano. Por comodidad, el transporte por defecto será “Carro Particular” (la
variable local transporte se declara con este valor). Si el argumento que se manda para el
parámetro carro en la aplicación de esta función es True entonces simplemente se retorna
el transporte por defecto. De lo contrario, se debe verificar el tiempo: si es mayor o igual a
una hora entonces el transporte será Bus, sino tenemos que consultar el dinero: si se tienen
los $30000 pero no hay problema con el tiempo (la tortuga necesita llegar entre 15 y 60
minutos) entonces se toma el Bus, sin embargo si hay prisa (15 minutos o menos) se tiene
que tomar Taxi.
62
? ? ?
5.2 Ejercicios
return transporte
FT
def transporte(dinero, tiempo, carro):
"Decide el medio de transporte para ir a un sitio"
transporte = "Carro Particular"
if not carro:
if tiempo >= 60:
transporte = "Bus"
else:
if dinero == 30000:
if tiempo > 15 and tiempo < 60:
transporte = "Bus"
else:
transporte = "Taxi"
else:
transporte = "Bus"
Algoritmo 5.5: Retorna el medio de transporte para ir a un sitio de acuerdo a unas
condiciones
Ejercicios
DR
A
5.2.
5.1 Dado el estado inicial del problema de mayorı́a de edad (ejemplo 5.1) y la función
esMayorDeEdad(), escriba el algoritmo necesario para que la tortuga vaya al sitio
adecuado dependiendo de la edad que tiene, deje una lı́nea punteada por el camino
que recorre y se abran las puertas del sitio, como en la figura 5.2.
5.2 Modifique los algoritmos necesarios del ejemplo 5.2 para que gráficamente se muestren
los disparos cuando se realicen (i.e. en las posiciones retornadas por la operación del
sistema aleatorio).
5.3 La fórmula de Pascua del ejemplo 4.6 funciona para cualquiera año en el rango
de 1900–2099 excepto para 1954, 1981, 2049 y 2076. Para estos 4 años la fórmula
produce una fecha que está una semana después. Escriba la función Pascua2() con
las modificaciones necesarias para que la fórmula funcione para todos los años.
5.4 Un año es bisiesto si es divisible por 4, a menos que sea un año que no es divisible
por 400 (1800 y 1900 no son bisiestos, mientras que 1600 y 2000 sı́ lo son). Escriba
la función Bisiesto() que retorne True si el año que le entra es bisiesto, y retorne
False de lo contrario.
63
5 Noción de Condición
5.5 Escriba la función FechaValida() que tenga tres parámetros correspondientes a una
fecha (dı́a, mes y año), y retorne True si la fecha es válida, y False de lo contrario.
Por ejemplo hdı́a: 24, mes: 5, año: 1962i es válida, pero hdı́a: 31, mes: 9, año: 2000i
no lo es (Septiembre solo tiene 30 dı́as).
FT
5.6 Los dı́as del año pueden numerarse del 1 al 365 (ó 366). Este número puede ser
calculado en tres pasos usando un sistema de números enteros:
a) N umeroDia = 31(mes − 1) + dia
b) si el mes está después de Febrero, reste (4mes + 23)/10
c) si es un año bisiesto y después de Febrero 29, sume 1
DR
A
Escriba la función NumeroDia() que tome una fecha (igual que el problema anterior,
es decir, representada en tres entradas dı́a, mes y año), verifique que es una fecha
válida (usando la función del problema anterior), y calcule el número asociado al dı́a
del año.
64
FT
6 Noción de Repetición
DR
A
En la mayorı́a de sistemas existen operaciones que se repiten una y otra vez. En el sistema
solar, por ejemplo, se ve que la traslación de los planetas se repite, al igual que la rotación
de la Tierra; en un sistema de producción las máquinas repiten un proceso de fabricación;
en la fórmula 1 los carros repiten un recorrido un número partı́cular de veces. Todas las
repeticiones mencionadas se hacen hasta que el sistema llega un estado deseado (algunas
de ellas son tantas que su cantidad podrı́a entenderse como infinito).
En modelos computacionales las repeticiones pueden hacerse de manera explı́cita o
implı́cita, es decir, con estructuras que controlan el flujo de la ejecución ó con aplicaciones circulares de funciones que vayan reduciendo las entradas hasta un caso base. Una
repetición explı́cita es comúnmente llamada iteración mientras que la aplicación circular de
una función (repetición implı́cita) es denominada recursión. A continuación se verá cada
una de ellas.
6.1.
Iteración
Un ciclo es una secuencia de aplicación de operaciones que se especifican una sola vez
pero son ejecutadas un número determinado de veces de manera sucesiva. Cada repetición
de la secuencia es llamada una iteración. El estado en el que queda el sistema después de
una iteración resulta ser el estado inicial de la siguiente iteración. Las iteraciones terminan
cuando se llega a un estado particular, es decir, se continua la ejecución del ciclo mientras
se cumpla una condición. Por ejemplo, la Tierra seguirá dando vueltas alrededor del Sol
mientras el sistema solar se encuentre en un estado en el que el Sol exista, i.e. mientras
se cumpla la condición de que el Sol siga ahı́; los corredores de la fórmula 1 dan vueltas
mientras el sistema se encuentre en un estado en el que los corredores no hayan dado un
número particular de vueltas, i.e. mientras se cumpla la condición de que el número de
vueltas de los corredores sea menor a un número k.
En modelos computacionales funciona igual. Supongamos que queremos crear un juego
muy simple de adivinar un número del 1 al 100. El jugador que quiere adivinar el número
solo tiene cinco oportunidades de adivinar. Cada vez que el jugador intenta adivinar se le
da una pista que consiste en decirle si el número a adivinar es menor o mayor al número
que acaba de decir. El algoritmo 6.1 codifica el juego anterior.
65
Ciclo
Iteración
6 Noción de Repetición
DR
A
FT
def adivinar(n):
"Procedimiento para jugar a adivinar un numero"
# Primera oportunidad
numero = input("Cual es el numero?")
if numero == n:
print("Adivino!!!")
else:
if numero > n:
print("El numero es menor")
else:
print("El numero es mayor")
# Segunda oportunidad
numero = input("Cual es el numero?")
if numero == n:
print("Adivino!!!")
else:
if numero > n:
print("El numero es menor")
else:
print("El numero es mayor")
# Tercera oportunidad
numero = input("Cual es el numero?")
if numero == n:
print("Adivino!!!")
else:
if numero > n:
print("El numero es menor")
else:
print("El numero es mayor")
# Cuarta oportunidad
numero = input("Cual es el numero?")
if numero == n:
print("Adivino!!!")
else:
if numero > n:
print("El numero es menor")
else:
print("El numero es mayor")
# Quinta oportunidad
numero = input("Cual es el numero?")
if numero == n:
print("Adivino!!!")
else:
print("Perdio, el numero era" + str(n))
Algoritmo 6.1: Juego de adivinar un número, sin ciclo
66
6.1 Iteración
FT
Si se aprecia bien el algoritmo de adivinar un número, puede detallarse que una porción
del código se repite varias veces haciendo que el código se torne aburrido y sin elegancia.
Adicionalmente, si el juego se extiende un poco, por ejemplo si el número de intentos se
incrementa, la implementación de este algoritmo se vuelve inmanejable. Por esta razón
es más conveniente utilizar un ciclo en este problema. El algoritmo 6.2 es equivalente al
anterior algoritmo solo que utilizando ciclos. Utilizamos una variable temporal llamada
oportunidad para saber cuantas veces se ha repetido el ciclo, y mientras dicha variable sea
menor o igual a cinco repetimos el proceso de pedir un número y saber si lo adivinó o no.
Es de notar que cuando se adivina el número se actualiza dicha variable temporal a cinco
para que el ciclo termine sin realizar el resto de iteraciones.
DR
A
def adivinar(n):
"Procedimiento para jugar a adivinar un numero"
oportunidad = 1
while oportunidad <= 5:
numero = input("Cual es el numero?")
if numero == n:
print("Adivino!!!")
oportunidad = 5
else:
if oportunidad == 5:
print("Perdio, el numero era" + str(n))
else:
if numero > n:
print("El numero es menor")
else:
print("El numero es mayor")
oportunidad = oportunidad + 1
Algoritmo 6.2: Juego de adivinar un número, con ciclo
Tal como puede verse en los anteriores algoritmos, para solicitar un dato al usuario e
imprimir información en pantalla, pueden usarse tres operaciones básicas de entrada y
salida, las cuales pueden verse en el cuadro 6.1.
El flujo de ejecución del algoritmo 6.2 (figura 6.1) muestra la semántica de un ciclo: el
cuerpo de un ciclo se ejecuta repetidamente mientras la condición sea cierta. Una vez la
condición sea falsa el ciclo termina. Cabe anotar que la condición de un ciclo, en este caso,
se prueba al comienzo del ciclo (llamado ciclo while ), lo que hace que si inicialmente la
condición es falsa, no se ejecute nada del cuerpo del ciclo.1
1
Existen otros tres tipos de ciclo: (1) aquel en el que la condición se prueba al final del ciclo, lo que
67
Ciclo while
6 Noción de Repetición
n
adivinar(n)
FT
oportunidad = 1
¿oportunidad <= 5?
Falso
Cierto
numero = input()
¿numero == n?
Cierto
print()
oportunidad = 5
Falso
¿oportunidad == 5?
DR
A
Cierto
Falso
print()
¿numero > n?
Cierto
print()
Falso
print()
oportunidad = oportunidad + 1
Figura 6.1: Flujo de ejecución de la función adivinar()
garantiza que el cuerpo del ciclo se ejecute por lo menos una vez (ciclo do-while), (2) aquel en el que
no se prueba una condición sino que se especifica explı́citamente cuántas iteraciones se harán en el ciclo
(ciclo for) y (3) aquel en el que se hace una iteración sobre los elementos de una lista (ciclo for-each).
68
6.1 Iteración
Operación
input(t)
raw input(t)
FT
print(t)
Acción
Solicita al usuario un dato por medio del texto t y retorna lo que
el usuario entre con el tipo de dato apropiado
Solicita al usuario un dato por medio del texto t, pero retorna lo
que el usuario entre como una cadena de texto
Imprime en pantalla el texto t
Cuadro 6.1: Operaciones básicas de entrada y salida
Los siguientes ejemplos muestran otros modelos computacionales que usan ciclos y las
operaciones del cuadro 6.1.
DR
A
Ejemplo 6.1
El juego Triqui (Tic-Tac-Toe en inglés) consiste en una grilla de 3 × 3, donde dos jugadores X y O se turnan colocando su marca en una posición vacı́a de la grilla. Cuando un
jugador logra colocar tres de sus marcas en lı́nea (vertical, horizontal o diagonal) gana el
juego. Luego, cada jugador lo que debe hacer es escoger una posición y marcarla, y esto se
debe hacer mientras el juego no haya terminado (i.e. no haya un ganador o el tablero no
esté lleno).
p1
p2
p3
p4
p5
p6
p7
p8
p9
Figura 6.2: Posiciones del juego Triqui
El algoritmo 6.3 muestra el código incompleto del juego. Dicho algoritmo está dividido en
tres partes: la inicialización de las variables locales, el juego como tal y la finalización donde
se conoce si hubo un ganador o quedó empatado el juego. En la primera parte puede verse
que el juego de Triqui se considera como un conjunto de nueve posiciones (p1 . . . p9) como
en la figura 6.2. Cada posición, inicialmente con la cadena vacı́a, puede contener el sı́mbolo
del jugador (X ó O). Como el juego es una secuencia de turnos, donde cada jugador realiza
En el capı́tulo 7 se verá el ciclo for-each.
69
6 Noción de Repetición
FT
def JuegoTriqui():
"Programa para jugar Triqui"
# Inicializa las variables locales
jugador = "X"
p1 = p2 = p3 = p4 = p5 = p6 = p7 = p8 = p9 = ""
DR
A
# Juego
while not TriquiTerminado(p1,p2,p3,p4,p5,p6,p7,p8,p9):
jugada = input(jugador + ", escribe tu posicion")
if jugada == 1:
p1 = jugador
elif jugada == 2:
p2 = jugador
elif jugada == 3:
p3 = jugador
elif jugada == 4:
p4 = jugador
elif jugada == 5:
p5 = jugador
elif jugada == 6:
p6 = jugador
elif jugada == 7:
p7 = jugador
elif jugada == 8:
p8 = jugador
elif jugada == 9:
p9 = jugador
ImprimirTriqui(p1,p2,p3,p4,p5,p6,p7,p8,p9)
if jugador == "X":
jugador = "O"
else:
jugador = "X"
# Final del Juego y Ganador
ganador = QuienGanoTriqui(p1,p2,p3,p4,p5,p6,p7,p8,p9)
if ganador == "X":
print("Gano la X")
elif ganador == "0":
print("Gano la O")
else:
print("Empatado")
Algoritmo 6.3: Juego de Triqui incompleto
70
6.1 Iteración
FT
la misma acción (decide en qué posición escribe su sı́mbolo) hasta que termine el juego,
esto se representa con segunda parte del algoritmo: mientras que el juego no está terminado (la negación de lo que retorna la función TriquiTerminado()) se pide al jugador la
posición donde decide colocar su sı́mbolo, se actualiza el tablero cambiando los valores de
las variables locales, se imprime (con la función ImprimirTriqui()) y se cambia el turno.
En la última parte se determina quién gana el juego con la función QuienGanoTriqui() y
se imprime el resultado.
? ? ?
Ejemplo 6.2
En un negocio de venta de productos al detal (e.g. una tienda de barrio, un supermercado o
restaurante) un cliente paga por un producto y si el dinero que entrega es mayor al precio
del producto, la empresa debe devolverle al cliente la cantidad excedente de dinero (el
cambio). Dicha cantidad debe ser desglosada en una denominación que sea factible dadas
las restricciones de billetes y monedas que existen, por ejemplo, si el excedente es 12500,
pero solo se tienen billetes de 10000, entonces no es posible dar el cambio, pero si se tienen
billetes de 10000, de 2000 y monedas de 500, entonces el cambio es factible de dar.
DR
A
def desglose():
"Procedimiento que imprime el desglose de una cantidad de dinero"
producto = 17500
dinero = input("Con cuanto va a pagar?")
cambio = dinero - producto
print("Su cambio es:")
denominacion = 50000
while cambio > 0:
cantidad = cambio/denominacion
if cantidad > 0:
print(str(cantidad) + "de" + str(denominacion))
cambio = cambio%denominacion
denominación = siguienteDenominacion(denominacion)
Algoritmo 6.4: Desglose de dinero
El algoritmo 6.4 es un procedimiento que pide al cliente el dinero para comprar un
producto e imprime la cantidad de billetes y monedas que debe dar como cambio. Se
asume un solo producto con un costo fijo de 17500 e igualmente se asume la función
siguienteDenominacion() la cual, dado un número que representa una denominación de
dinero, retorna la siguiente denominación en orden descendente, i.e. si se le pasa como
argumento (un billete de) 50000, retornará (un billete de) 20000 (es decir, la siguiente
71
6 Noción de Repetición
denominación), si se le pasa 20000, retornará 10000, y ası́ sucesivamente.2
? ? ?
FT
Ejemplo 6.3
Supongamos que queremos imprimir la lista de los números primos del 1 al n. Para hacer
esto debemos hacer un ciclo desde 1 hasta n imprimiendo el número i (1 ≤ i ≤ n) en
cada iteración. Sin embargo i se debe imprimir solo si es primo y esto lo sabemos si dicho
número es divisible solo entre 1 y él mismo, es decir, si el residuo de la división entre i y
todos los números entre 2 y i − 1 es diferente de cero. Para esto último debemos hacer otro
ciclo. El algoritmo 6.5 muestra el anterior procedimiento.
def primos(n):
"Procedimiento que imprime los números primos de 1 a n"
i = 1
while i < n:
esprimo = True
j = 2
while j <= i-1:
if i%j == 0:
esprimo = False
j = j + 1
if esprimo == True:
print(i)
i = i + 1
DR
A
Ciclos Anidados
Existen algunos problemas cuya solución requiere que en el cuerpo del ciclo, es decir, en
medio de las operaciones que se quieren repetir, hayan otros ciclos. Estos son comúnmente
llamados ciclos anidados.
Algoritmo 6.5: Imprime la lista de número primos entre 1 y n
? ? ?
Es normal que en algunos problemas el objetivo que se quiere lograr al realizar un ciclo
se cumpla antes de terminar el ciclo, es decir, cuando todavı́a la condición es cierta. Para
2
Es de notar que en el algoritmo 6.4 el desglose comienza desde la denominación más alta hasta la mas
pequeña. Esta es la forma más simple de hacerlo, pero no es la única. Un estudiante puede afirmar que
se podrı́a dar cambio de 12500 solo con monedas de 500 y no como se mencionó arriba. Lo importante
aquı́ es saber que el problema de encontrar todos los posibles desgloses de dinero es un problema
combinatorio, y por lo tanto, muy difı́cil de resolver.
72
6.1 Iteración
Rompimiento
FT
estos casos resulta ineficiente continuar realizando iteraciones ya que lo que se pretendı́a ya
se ha cumplido. Hay dos posibles soluciones para estos problemas: (1) forzar manualmente
a que se incumpla la condición del ciclo, ó (2) usar una instrucción de rompimiento. Un
rompimiento 3 es una estructura de control que altera la forma de proceder de una iteración, causando que el ciclo más interno en el que se encuentra el rompimiento se termine
inmediatamente cuando es ejecutado.
De igual manera, en algunos ciclos resulta útil que en algún punto de la iteración el flujo
de ejecución se mueva a la siguiente iteración sin continuar más allá en el cuerpo de la
actual iteración. Estas estructuras de control son llamadas continuaciones.
En el ejemplo 6.4 se muestra una situación común donde el uso de los rompimientos y
continuaciones es adecuado.
DR
A
Ejemplo 6.4
Supongamos que necesitamos hacer un interpretador on-line del lenguaje de programación
Python. Esta es una tarea bastante laboriosa y requiere un conocimiento muy avanzado,
por lo que queremos empezar simplemente quitando los comentarios, ya que estos, por
definición, son solo anotaciones y siempre son ignorados por los interpretadores. Para esto,
entonces, debemos pedir al usuario que vaya ingresando lı́nea por lı́nea, el código del programa que está desarrollando, y cada vez que el usuario escribe una lı́nea, revisar el primer
carácter de dicha lı́nea y si es un sı́mbolo “#” significa que esa lı́nea es un comentario y
no debe ser interpretada. El algoritmo 6.6 muestra este procedimiento.
Puede notarse que la condición del ciclo es la constante True, esto significa que la condición siempre será cierta y por lo tanto el número de iteraciones está indeterminado. Lo
anterior es necesario ya que de antemano no se sabe cuántas lı́neas de código va a ingresar el usuario. Una vez se obtiene la lı́nea de código (un texto), se pregunta si el primer
caracter de dicho texto es el sı́mbolo “#” y si la respuesta es afirmativa no hay necesidad
de seguir con el resto del cuerpo del ciclo sino que simplemente se vuelve a pedir una lı́nea
de código. Si la respuesta es negativa se revisa si lo que hizo fue presionar enter en cuyo
caso se revisa si se ha presionado enter dos veces seguidas y se termina la interpretación,
es decir, se interrumpe el ciclo. Si no pasa lo anterior, entonces se aplica el procedimiento
para interpretar el código que se ha introducido, el cual no será implementado aquı́.
3
? ? ?
Hasta el dı́a de hoy existe una fuerte discusión sobre si usar rompimientos es una buena o mala práctica de
programación. Nosotros pensamos que todo depende del uso que se haga de la instrucción, e invitamos a
los lectores a desarrollar varios ejemplos usándola y leer el famoso artı́culo de Donald Knuth, “Structured
Programming with go to Statements” [2] para sacar sus propias conclusiones.
73
Continuación
6 Noción de Repetición
FT
def quitarComentarios():
"Procedimiento que recibe lineas codigo en python"
"las envia a interpretar, excepto los comentarios"
print("Comienzo de la Interpretacion")
enter = 1
# Ciclo para capturar todas las lineas
while True:
# Pide una linea de codigo al usuario
linea = raw_input(">>> ")
# Verifica si la linea es un comentario
if string.find(linea,"#") == 1:
continue
DR
A
# Verifica si termina el codigo
if linea == "":
if enter == 2:
print("Fin de la Interpretacion")
break
else:
enter = enter + 1
# Envia la linea a interpretar y continua
else:
Interpretar(linea)
enter = 1
Algoritmo 6.6: Recibe lı́neas de código y quita los comentarios
6.2.
Recursión
A diferencia de la repetición por medio de iteración, la repetición por medio de recursión
no cambia el estado del sistema en cada repetición. Lo que hace es abstraer el código a
repetir y luego repite la aplicación de dicha abstracción reduciendo los argumentos en cada
repetición hasta cumplir una condición. De esta manera la recursión hace que el problema
que se está resolviendo se divida en dos o mas piezas conceptuales (i.e. idea matemática
de dividir y conquistar), cada una de ellas siendo una versión mas pequeña del problema
original.
Los fractales son ejemplos reales de la idea de recursión. En la figura 6.34 puede verse
un helecho, el cual está constituido de helechos con una medida más pequeña, que a su vez
4
Imagen tomada de http://www.fresh-paper.com/
74
6.2 Recursión
DR
A
FT
están constituidos de helechos mas pequeños, y ası́ sucesivamente.
Figura 6.3: Fractal
Como en recursión el conjunto de operaciones que se quiere repetir es abstraı́do en un
procedimiento o función, la forma de hacer repetición es aplicando dicho procedimiento o
función dentro de la misma abstracción. De allı́ que la noción de recursión sea descrita
como una operación definida en términos de sı́ misma. Por ejemplo, encontrar el factorial
de un número n es igual a encontrar el factorial del número anterior, n − 1, y multiplicar
su resultado por n, es decir, f act(n) = f act(n − 1) × n.
Sin embargo, si desarrollamos la recursión del factorial ası́ como está: f act(n) = n ×
75
Recursión
6 Noción de Repetición
f act(n − 1), podemos ver que es infinita, es decir, nunca para:
f act(n) = n × f act(n − 1)
f act(n − 1) = (n − 1) × f act(n − 2)
FT
f act(n − 2) = (n − 2) × f act(n − 3)
..
.
Para evitar esto es necesario garantizar que en algún punto la recursión se detenga. Ese
punto donde la recursión para es llamado el caso base. El caso base de la función factorial es
el factorial de cero, ya que esta función no está definida para número negativos. Entonces si
decimos que f act(0) = 1, vemos que la función general (también llamada paso de reducción)
funciona hasta que llega a este punto, donde se termina la recursión. La implementación
completa de la función factorial está en el algoritmo 6.7.
DR
A
def factorial(n):
"Funcion que halla el factorial de un numero"
if n == 0:
return 1
else:
return n * factorial(n-1)
Algoritmo 6.7: Halla el factorial de un número n
Seguir el flujo de ejecución de un algoritmo recursivo no es algo intuitivo ya que es
necesario estar muy atento al nivel de recursión en el que se encuentra la ejecución. El
nivel de recursión está dado por el número de aplicaciones del paso de reducción: cada
vez que se aplica el paso de reducción se aumenta el nivel de recursión hasta que se llega
al caso base, una vez allı́ se comienza a devolver en los niveles hasta volver a la primera
aplicación (nivel cero). La figura 6.4 muestra gráficamente el flujo de la aplicación de la
función factorial del algoritmo 6.7 para n = 5. Cada cuadro de la figura representa una
aplicación de la función factorial(); cuando se hace la primera aplicación (nivel 0), n es
igual a 5, luego la condición es falsa y el flujo de ejecución se va por el paso de reducción
(return 5*factorial(n-1)). Como el resultado de factorial(5-1) no se conoce, esto
hace que se haga una nueva aplicación de la función y, por lo tanto, aumente el nivel de
recursión (nivel 1). En esta nueva aplicación n es igual a 4, entonces la condición es falsa y,
con factorial(4-1) desconocido, de nuevo el flujo se va por el paso de reducción, se hace
una nueva aplicación de la función (nivel 2). Esto se repite tres veces mas hasta que en la
aplicación de la función n sea igual a cero; en este caso la condición es cierta y entonces el
76
6.2 Recursión
n=5
factorial(5)
nivel 0
¿n == 0?
Cierto
return 1
Falso
return 5 * factorial(n-1)
n=4
factorial(4)
nivel 1
¿n == 0?
Cierto
return 1
Falso
return 4 * factorial(n-1)
retorna 24
n=3
factorial(3)
nivel 2
¿n == 0?
Cierto
return 1
FT
retorna 120
Falso
return 3 * factorial(n-1)
retorna 6
n=2
DR
A
factorial(2)
nivel 3
¿n == 0?
Cierto
return 1
Falso
return 2 * factorial(n-1)
retorna 2
n=1
factorial(1)
nivel 4
¿n == 0?
Cierto
return 1
Falso
return 1 * factorial(n-1)
retorna 1
n=0
¿n == 0?
Cierto
return 1
factorial(0)
nivel 5
Falso
return n * factorial(n-1)
retorna 1
Figura 6.4: Flujo de ejecución de la función factorial(5)
77
6 Noción de Repetición
FT
flujo de ejecución cambia y la función, en el nivel 5 de recursión, retorna 1. Este cambio en
el flujo hace que se empiece a conocer el resultado de las aplicaciones de las función: en el
nivel 4, factorial(1-1) es igual a 1, de allı́ que la función factorial en el nivel 4 retorne
1 × 1 = 1; este resultado hace que se conozca factorial(2-1) y se retorne 2 × 1 = 2 en el
nivel 3; y ası́ sucesivamente hasta volver al nivel 0 donde se retornará el resultado final.
A continuación se muestran otros ejemplos de algoritmos recursivos.
DR
A
Ejemplo 6.5
Cuenta la leyenda que en un templo de Hanoi, bajo la cúpula que señala el centro del mundo,
hay una bandeja de bronce con tres largas agujas. Al crear el mundo, Dios colocó en una
de ellas sesenta y cuatro discos de oro, cada uno de ellos más pequeño que el anterior hasta
llegar al de la cima. Dı́a y noche, incesantemente, los monjes transfieren discos de una
aguja a otra siguiendo las inmutables leyes de Dios, que dicen que debe moverse cada vez
el disco superior de los ensartados en una aguja a otra y que bajo él no puede haber un
disco de menor radio. Cuando los sesenta y cuatro discos pasen de la primera aguja a otra,
todos los creyentes se convertirán en polvo y el mundo desaparecerá con un estallido.5
El objetivo es modelar computacionalmente este problema. La situación inicial del problema para cuatro discos está en la figura 6.5.
Figura 6.5: Torres de Hanoi - Configuración inicial
Y se desea pasar a la situación final de la figura 6.6.
Figura 6.6: Torres de Hanoi - Configuración final
5
La leyenda fue inventada por De Parville en 1884, en “Mathematical Recreations and Essays”, un libro
de pasatiempos matemáticos. La ambientación era diferente: el templo estaba en Benarés y el dios era
Brahma.
78
6.2 Recursión
FT
Aunque sólo se puede tocar el disco superior de un montón, se debe pensar en el disco
del fondo. Ese disco debe pasar de la primera aguja a la tercera, y para que eso sea posible,
se debe alcanzar la configuración de la figura 6.7.
Figura 6.7: Torres de Hanoi - Configuración intermedia 1
DR
A
Sólo en ese caso se puede pasar el disco más grande a la tercera aguja, es decir, alcanzar
la configuración de la figura 6.8.
Figura 6.8: Torres de Hanoi - Configuración intermedia 2
Está claro que el disco más grande no se va a mover ya de esa aguja, pues es su destino
final. La pregunta que surge entonces es: ¿Cómo se han pasado los tres discos superiores
a la segunda aguja? Pues simple, pasar una pila de tres discos de una aguja a otra no es
más que el problema de las torres de Hanoi para una torre de tres discos. De este punto lo
que falta por hacer es mover la pila de tres discos de la segunda aguja a la tercera, y eso,
nuevamente, es el problema de la torres de Hanoi para tres discos. Ahı́ aparece la recursión.
Resolver el problema de las torres de Hanoi con n discos requiere entonces:
resolver el problema de las torres de Hanoi con n − 1 discos, aunque pasándolos de
la aguja inicial a la aguja libre;
mover el último disco de la aguja en que estaba inicialmente a la aguja de destino;
y resolver el problema de las torres de Hanoi con n − 1 discos de la aguja libre a la
aguja final.
Hay un caso trivial o caso base: el problema de la torres de Hanoi para un solo disco
(basta con mover el disco de la aguja en la que esté insertado a la aguja final).
79
6 Noción de Repetición
Los parámetros que necesita el procedimiento son el número de discos que vamos a
mover, la aguja origen y la aguja destino. Se identificará cada aguja con un número. El
procedimiento se encuentra en el algoritmo 6.8.
FT
def torresHanoi(n, inicial, final):
"Procedimiento para resolver el problema de las torres de Haoi"
if n == 1:
print("Mover el disco superior de la aguja " + str(inicial))
print("a la aguja " + str(final))
else:
# Determinar cual es la aguja libre
if inicial != 1 and final != 1:
libre = 1
else:
if inicial != 2 and final != 2:
libre = 2
else:
libre = 3
# Primer subproblema: mover n-1 discos de inicial a libre
torresHanoi(n-1, inicial, libre)
DR
A
print("Mover el disco superior de la aguja " + str(inicial))
print("a la aguja " + str(final))
# Segundo subproblema: mover n-1 discos de libre a final
torresHanoi(n-1, libre, final)
Algoritmo 6.8: Imprime el proceso para solucionar las torres de hanoi de n discos
Ahora, para resolver el problema con n = 4 se hace el llamado al procedimiento torresHanoi(4,1,3). El programa imprimirá las órdenes correspondientes a los
movimientos de la figura 6.9.
Interfaz Gráfica
? ? ?
La solución para el problema de las torres de Hanoi está bien, pero no muestra gráficamente el proceso, es decir, solo describe textualmente los pasos para resolver el problema.
Para los siguientes problemas vamos a introducir un sistema para desarrollar interfaces
gráficas llamado Tkinter6 . Una interfaz gráfica es un espacio de interacción entre una persona y un programa con imágenes en vez de comandos de texto. Algunas operaciones del
6
El sistema Tkinter (“Tk Interface”) es la interfaz estándar de Python para el sistema gráfico Tk GUI
toolkit.
80
6.2 Recursión
2)
3)
4)
5)
6)
7)
8)
9)
10)
11)
12)
13)
14)
15)
16)
FT
1)
Figura 6.9: Torres de Hanoi - Proceso completo para n = 4
sistema de interfaces gráficas Tkinter pueden verse en el cuadro 6.2.
Acción
Crea y retorna la ventana principal de un programa
Crea y retorna un nuevo botón en la ventana v con
texto t y que realiza la acción a cuando se oprime
Crea y retorna una nueva etiqueta en la ventana v
con texto t
Crea y retorna un nuevo campo de texto en la ventana v para un número de caracteres c
Crea y retorna un nuevo campo de dibujo en la
ventana v de ancho w y alto h
Toma el widget y lo hace visible
Hace que la ventana se quede esperando los eventos
que puedan ocurrir hasta que se cierre la ventana
DR
A
Operación
Tk()
Button(v,text=t,command=a)
Label(v,text=t)
Text(v,width=c)
Canvas(v,width=w,height=h)
pack()
mainloop()
Cuadro 6.2: Operaciones básicas del sistema Tkinter
Ejemplo 6.6
El Triángulo de Sierpinski es un fractal creado por Waclaw Sierpiński en 1915. El concepto
del Triángulo de Sierpinski es muy simple: Se toma un triángulo (usualmente, pero no
necesariamente, equilátero) como la primera imagen de la figura 6.10; se conectan los
puntos medios de cada lado para formar cuatro triángulos separados y se corta el triángulo
del centro, como en la segunda imagen de la figura; para cada uno de los tres triángulos
81
6 Noción de Repetición
FT
restantes se realiza el mismo proceso como en la tercera imagen de la figura; y se repite el
proceso indefinidamente construyendo la imagen final de la figura.
...
Figura 6.10: Triángulo de Sierpinski
DR
A
La construcción de este fractal muestra claramente una recursión que puede ser implementada como la función sierpinski() del algoritmo 6.9. La idea de este algoritmo se
centra en que el nivel de recursión en el que se encuentre el proceso determina el número
de triángulos a dibujar: si estamos en un nivel inicial (cero) solo se dibuja un triángulo, en
el nivel uno se dibujan tres triángulos, en el nivel dos se dibuja nueve y ası́ sucesivamente.
Lo importante a notar es que cada triángulo que se va a dibujar tiene una posición particular y un tamaño especı́fico, y entre más alto sea el nivel, la posición cambiará de manera
monótona y dicho tamaño es más pequeño (el tamaño de un lado de cualquiera de los tres
triángulos es la mitad del tamaño de un lado del triángulo superior).
Los parámetros del procedimiento sierpinski() incluyen el canvas y las coordenadas
x y y donde será dibujado el triángulo, el tama~
no del triángulo a dibujar y el nivel en el que
se encuentra la recursión. En el nivel cero simplemente se dibuja un triángulo usando el
procedimiento para crear polı́gonos (véase el cuadro 6.3); en cualquier otro nivel se realizan
tres llamados recursivos, correspondientes a los tres triángulos que se deben dibujar dentro
del triángulo superior.
El procedimiento gui-sierpinski() en el algoritmo 6.9 recibe como parámetro el nivel
de profundidad del Triángulo de Sierpinski. Su proceso es simple: primero crea una ventana
y se la asigna a la variable v; entonces dentro de dicha ventana crea un canvas (asignado a
la variable miCanvas) de tamaño 500×500 donde se dibujará el Triángulo de Sierpinski y se
hace visible con la operación miCanvas.pack(); luego se hace el llamado al procedimiento
para construir y dibujar el triángulo enviándo como argumento el canvas recién creado,
la posición dentro del canvas (100,400), el tamaño del triángulo más grande y el nivel de
profundidad; finalmente se aplica la operación para dejar a la ventana v lista para cualquier
82
6.3 Ejercicios
evento.
FT
def sierpinski(canvas, x, y, tamano, nivel):
"Procedimiento que dibuja el triangulo de sierpinski"
if (nivel == 0):
canvas.create_polygon(x, y,
x+tamano, y,
x+tamano/2, y-tamano*math.sqrt(3)/2,
outline="black",
fill="orange")
else:
sierpinski(canvas, x, y, tamano/2, nivel-1)
sierpinski(canvas, x+tamano/2, y, tamano/2, nivel-1)
sierpinski(canvas,
x+tamano/4, y-tamano*math.sqrt(3)/4,
tamano/2, nivel-1)
DR
A
def gui-sierpinski(nivel):
"Procedimiento que dibuja la ventana del triangulo de sierpinski"
v = Tkinter.Tk()
miCanvas = Tkinter.Canvas(v, width=500, height=500)
miCanvas.pack()
sierpinski(miCanvas, 100, 400, 300, nivel)
root.mainloop()
Algoritmo 6.9: Dibuja el triángulo de Sierpinski
Puede intuirse entonces que si se quisiera crear un Triángulo de Sierpinski con una
profundidad 4, se deberı́a hacer la aplicación del procedimiento gui-sierpinski(5).
6.3.
? ? ?
Ejercicios
6.1 Complete el juego de Triqui con las operaciones que no están implementadas:
TriquiTerminado() recibe como parámetros las nueve posiciones de un tablero
de Triqui y retorna True si alguno de los dos jugadores ganó ó si el tablero ya
está completo y ninguno de los jugadores ganó, de lo contrario retorna False.
ImprimirTriqui() recibe como parámetros las nueve posiciones de un tablero
de Triqui e imprime el tablero de Triqui de una manera visualmente correcta
(i.e. como se ve normalmente el juego).
83
6 Noción de Repetición
Operación
create arc(x0,y0,x1,y1)
create bitmap(x,y,bitmap=b)
create oval(x0,y0,x1,y1)
FT
create image(x,y,image=i)
create line(x0,y0,x1,y1,...,xn,yn)
create polygon(x0,y0,x1,y1,...,xn,yn)
create rectangle(x0,y0,x1,y1)
DR
A
create text(x,y,text=t)
Acción
Construye un arco desde el punto
(x0,y0) hasta el punto (x1,y1)
Muestra el mapa de bits b en el punto
(x,y)
Muestra la imagen i en el punto (x,y)
Construye una lı́nea que va por la serie de puntos (x0,y0), (x1,y1), . . . ,
(xn,yn)
Construye el óvalo que calza en el
rectángulo definido por los puntos
(x0,y0) y (x1,y1)
Construye un polı́gono cuya geometrı́a
es especificada por los vértices definidos con los puntos (x0,y0), (x1,y1),
. . . , (xn,yn)
Construye el rectángulo definido por
los puntos (x0,y0) y (x1,y1)
Muestra el texto t en el punto (x,y)
Cuadro 6.3: Operaciones para dibujar en un Canvas de Tkinter
QuienGanoTriqui() recibe como parámetros las nueve posiciones de un tablero
de Triqui y retorna una cadena de texto solo con el caracter correspondiente al
ganador del juego (‘‘X’’ o ‘‘O’’). Si no hubo ganador, la función debe retornar
un sı́mbolo diferente.
6.2 El juego de Triqui del algoritmo 6.3 tiene algunos problemas, por ejemplo un jugador
puede seleccionar una posición donde ya habı́a un sı́mbolo, ó si un jugador no ingresa
un número entre 1 y 9 (las posiciones del tablero), pierde el turno. Corrija estos y
otros problemas que tiene el juego.
6.3 El algoritmo 6.4 tiene dos problemas, (1) si se paga con una cantidad menor al
costo del producto, no se da cambio, pero tampoco se especifica que le falta dinero
y (2) la función siguienteDenominacion() no está implementada. Solucione estos
problemas.
6.4 Asuma que en el problema del desglose de dinero se tiene una cantidad limitada de
billetes y monedas. Modifique el algoritmo 6.4 para que se tenga en cuenta el número
84
6.3 Ejercicios
de billetes y monedas y, llegado el caso, imprima que no es posible dar el cambio
debido a que no se cuenta con las denominaciones necesarias.
FT
6.5 Asuma que el algoritmo solución al problema del desglose va a ser usado en un
restaurante. Complete el algoritmo para que muestre un menú de comida, le pida al
usuario seleccionar la comida que quiera (pueden ser varios platos), luego le pase la
cuenta y muestre el cambio dado lo que el cliente dio de dinero.
6.6 Mejore el algoritmo del punto anterior (6.5) haciendo que haya un número n de
clientes, los cuales ven el menú, escogen la comida y pagan. Este nuevo algoritmo
debe retornar la cantidad de dinero que pagaron todos los clientes del restaurante.
6.7 Muestre el flujo de ejecución de la aplicación del procedimiento torresHanoi(5,1,3).
6.8 Pruebe la función torresHanoi() haciendo el llamado con los 64 discos de la leyenda,
es decir torresHanoi(64,1,3). ¿Cuántos movimientos deben hacer los monjes?
DR
A
6.9 De manera general ¿cuántos movimientos son necesarios para resolver el problema con
n discos? Para responder esta pregunta escriba una función NumMovimientosHanoi()
que reciba un número y devuelva el número de movimientos necesarios para resolver
el problema de las torres de Hanoi con ese número de discos (se debe utilizar la
función torresHanoi()).
6.10 Modifique el algoritmo 6.8 para mostrar gráficamente el proceso de solución de las
Torres de Hanoi. Puede usar el Mundo de la Tortuga o el sistema Tkinter.
85
DR
A
FT
6 Noción de Repetición
86
FT
7 Noción de Abstracción de Datos
En el capı́tulo 4 se describió la abstracción como el proceso en el que datos y algoritmos son agrupados dentro de una categorı́a que los conecta. En este capı́tulo veremos la
abstracción que involucra datos.
7.1.
Listas
DR
A
La abstracción de datos, al igual que la abstracción de control, permite “ocultar” información de manera que se presenten solo los datos relevantes a un contexto particular. De
esta forma se hace visible al usuario solo una interfaz de los datos mientras que los datos
como tal se vuelven privados y son accedidos solo a través de dicha interfaz. Las interfaces, en general, son herramientas computacionales que sirven como punto de interacción
entre componentes, los cuales pueden ser de bajo nivel como los sistemas operativos que
permiten interactuar piezas de hardware con programas, o de más alto nivel como gráficas (que brevemente se describieron en el capı́tulo anterior) y estructuras de datos. Una
estructura de datos es un grupo de piezas de información reunidas bajo un mismo nombre. Su propósito es organizar eficientemente dicha información de manera que operaciones
como búsqueda y ordenamiento se realicen de la mejor manera posible y se conserven las
propiedades matemáticas que puedan existir en esas operaciones. Las estructuras de datos
comprenden, entre muchos otras, arreglos, registros, conjuntos, pilas, colas, árboles, grafos
y tablas hash, pero quizás las más usadas sean las listas.
Una lista es una secuencia de datos llamados elementos los cuales pueden ser accedidos
directamente por medio de un ı́ndice. Para una lista X, el primer elemento tiene ı́ndice
cero, es decir es el elemento X[0], el segundo elemento tiene ı́ndice uno, o sea que es el
X[1], y ası́ sucesivamente hasta el último elemento cuyo ı́ndice es igual al tamaño de la
lista menos uno, es decir que si n es el número de elementos de la lista, el último elemento
será X[n − 1].
Para ejemplificar la noción de lista y la necesidad de contar con ella, consideremos
un juego simple como el ahorcado. Este juego consiste en dos jugadores, uno de ellos
piensa en una palabra y dibuja lı́neas que representan las letras de dicha palabra, y el otro
jugador debe descifrar cuál es esa palabra secreta. En cada turno el primer jugador dice
una letra y si esta letra pertenece a la palabra secreta el otro jugador escribirá la letra
sobre la correspondiente lı́nea, pero si la letra no pertenece a la palabra el segundo jugador
87
Interfaz
Estructura de Datos
Lista
7 Noción de Abstracción de Datos
dibujará una parte de un hombre ahorcado. Si el primer jugador puede adivinar la palabra
secreta antes que se dibuje por completo el ahorcado, este gana, de lo contrario pierde. La
figura 7.1 muestra un juego de ahorcado: el primer jugador ha acertado 5 letras y fallado
igual número de veces, por esto el dibujo del ahorcado está muy cerca de terminarse.
FT
Letras Falladas:
U, S, E, T, L, B, V, K, Q
RA
A
DR
A
PRO
ON
Figura 7.1: Juego Ahorcado
Es de notar que ahorcado es posible convertirlo en un juego de un jugador contra el
computador ya que el segundo jugador que se nombró arriba solo se limita a interactuar
con las jugadas del primer jugador, es decir, solo selecciona una palabra y, cada vez que
el primer jugador dice una letra, verifica dicha letra y realiza la acción correspondiente:
escribir la letra en el espacio adecuado ó dibujar una parte del cuerpo del ahorcado. La
palabra seleccionada por el segundo jugador debe ser parte de un conjunto de palabras
que conoce, lo suficientemente grande para que se pueda jugar una y otra vez cambiando
la palabra secreta y que ası́ el primer jugador no sepa cuál es de manera anticipada. Si
usáramos una variable para cada palabra, se tendrı́a una cantidad absurda e inmanejable
de variables, y si a eso le adicionamos las variables necesarias para conocer cuáles son las
letras que ya se han probado, se complica aún mas el algoritmo. Por esto son indispensables
unas estructuras de datos que reúnan y organicen las palabras y las letras sin necesidad de
crear dicha cantidad de variables.
El procedimiento para jugar ahorcado se encuentra en el algoritmo 7.1. Se cuenta con tres
listas listaPalabras, letrasAcertadas y letrasFalladas. El propósito de listaPalabras
es intuitivo (aunque deberı́a tener muchos mas elementos para hacer el juego más diver-
88
7.1 Listas
# Dibuja la ventana inicial
ventana = saludoInicial()
FT
def juegoAhorcado():
"Procedimiento para un juego de ahorcado"
listaPalabras = ["abstraccion", "ciclo", "declaracion", "estado",
"flujo", "implementacion", "grafica", "lista",
"modelo", "parametro", "recursion", "sistema"]
indice = random.randint(0, len(listaPalabras)-1)
palabraSecreta = listaPalabras[indice]
letrasAcertadas = []
letrasFalladas = []
juegoAcabado = False
# Ciclo del juego
while not juegoAcabado:
# Dibuja/Actualiza el tablero
dibujarTablero(ventana, palabraSecreta,
letrasAcertadas, letrasFalladas)
DR
A
# Pide una letra al jugador
letra = pedirLetra(ventana)
# Procede de acuerdo a la letra dada
letrasAcertadas.append(letra)
if letra in palabraSecreta:
# Chequea si encontro todas las letras
num = 0
completoPalabra = True
while num < len(palabraSecreta):
if not palabraSecreta[num] in letrasAcertadas:
completoPalabra = False
break
num = num + 1
if completoPalabra:
acabarJuego(ventana, True)
juegoAcabado = True
else:
# Chequea si se ha ahorcado
if len(letrasFalladas) == 10:
acabarJuego(ventana, False)
juegoAcabado = True
Algoritmo 7.1: Juego ahorcado
89
7 Noción de Abstracción de Datos
Acción
Agrega el elemento x al final de la lista
Inserta el elemento x en la posición i de la lista
Borra el primer elemento de la lista que tenga valor x
Retorna y borra el elemento de la lista cuya posición es i
Retorna el tamaño de la lista l
Retorna un booleano que indica si el elemento x se encuentra
en la lista l
Retorna una lista con los números del cero al n-1 como
elementos
DR
A
Operación
append(x)
insert(i,x)
remove(x)
pop(i)
len(l)
x in l
FT
tido). Las otras dos listas sirven para llevar un registro de las letras que el jugador va
diciendo, en una van las letras que efectivamente se encuentran en la palabra secreta y en
la otra aquellas que no.
Al inicio del juego se toma una palabra de manera aleatoria de la lista listaPalabras
y se asigna a la variable palabraSecreta. Luego se da un saludo inicial (en teorı́a se
debe mostrar una splash screen 1 ) con un procedimiento no implementado aquı́ llamado
saludoInicial(), y después arranca el ciclo del juego: primero dibuja o actualiza el tablero
con el procedimiento dibujarTablero(), el cual debe mostrar una imagen como la figura
7.1 dada la palabra secreta y las listas de registro de letras; acto seguido le pide una letra
al jugador con la función pedirLetra(); por último, de acuerdo a la letra dada se realiza
el proceso correspondiente, es decir, agregar la letra a la lista letrasAcertadas o a la lista
letrasFalladas y, si es el caso, terminar el juego ya sea porque encontró todas las letras
de la palabra secreta o porque falló diez letras y se terminó de dibujar el ahorcado.
En el algoritmo 7.1 puede verse el uso de algunas operaciones para manejar listas como
append y in. Estas y otras operaciones básicas del sistema de listas se pueden ver en el
cuadro 7.1.
range(n)
Cuadro 7.1: Operaciones básicas del sistema de listas
Las operaciones saludoInicial(), dibujarTablero(), pedirLetra() y acabarJuego()
aplicadas en el algoritmo 7.1 realizan procesos gráficos, por lo que pueden ser implementadas usando el sistema TkInter. Sin embargo, dado que ahorcado es un juego, podemos
usar un sistema especializado en la construcción de juegos. De allı́ que vamos a introducir
pygame, un sistema para el desarrollo de juegos.
1
Una splash screen o pantalla de inicio, es una imagen que se muestra al inicio de un programa para presentar el logo y/o tı́tulo del programa, y además para notificar al usuario que el programa se
está cargando.
90
7.1 Listas
FT
Pygame2 es una librerı́a diseñada para construir software multimedia. Cuenta
con operaciones para manejo de video y sonido que permiten desarrollar video
juegos. De igual manera, pygame tiene funciones para manejar gráficos 2D,
música, entradas, fuentes, detección de colisiones, gráficos 3D con OpenGL,
joysticks, pelı́culas, etc.
Las operaciones básicas y algunas constantes de pygame se pueden ver en el cuadro 7.2.
Operación
init()
quit()
display.set mode(r)
display.update()
event.get()
mouse.get pos()
DR
A
font.SysFont(f,t)
draw.rect(s,c,r,w)
Acción
Inicializa todo el sistema pygame
Termina el sistema
Inicializa una ventana para trabajar y retorna un display
(dispositivo de salida). Su parámetro r representa la resolución de la ventana (una pareja (w, h) donde w es el ancho y
h es el alto de la ventana)
Actualiza la ventana
Retorna una lista con los eventos que recibe el sistema
Retorna una pareja, i.e. lista de dos elementos, con la posición (x, y) de la ventana donde se hizo clic con el mouse
Retorna la fuente con tipo f y tamaño t para ser usada
Dibuja un rectángulo en la superficie s con color c, anchura
del borde w (w=0 significa que el rectángulo estará lleno del
color c) y cuyos puntos se encuentran en las posiciones dadas
por los elementos de la lista r
Carga y retorna la imagen contenida en el archivo f
Toma la imagen i y la escala a las nuevas dimensiones (w,
h)
Carga el archivo de sonido w
Interpreta el archivo de sonido cargado previamente
image.load(f)
transform.scale(i,(w,h))
mixer.music.load(w)
mixer.music.play()
Constantes
QUIT
KEYUP
KEYDOWN
MOUSEMOTION
MOUSEBUTTONUP
MOUSEBUTTONDOWN
K RETURN
K SPACE
K A3
Cuadro 7.2: Operaciones básicas y algunas constantes del sistema Pygame
2
3
http://www.pygame.org/
Las constantes para todos los demás botones del teclado tienen la misma forma: K <tecla>.
91
7 Noción de Abstracción de Datos
A continuación, en el ejemplo 7.1, se desarrollan las funciones y procedimientos no implementados del procedimiento juegoAhorcado() en el algoritmo 7.1, usando operaciones
del sistema pygame.
FT
Ejemplo 7.1
DR
A
La función saludoInicial() (algoritmo 7.2) comienza inicializando el sistema pygame y
construyendo la ventana principal del programa (que puede verse en la figura 7.2). Después
de esto selecciona la fuente con la que se escribirá en esta función, que en este caso es
“Arial” de tamaño 30. Acto seguido asigna las variables que contienen las frases que se van
a imprimir en la pantalla. Dichas frases deben ser renderizadas, es decir, se deben generar
imágenes a partir de unos modelos, que en este caso son texto. La renderización se produce
aplicando la operación render() del módulo de fuentes del sistema (las operaciones de este
módulo pueden verse en el cuadro 7.3). Luego comienza un ciclo infinito en el cual primero
se borra completamente la pantalla, se se muestran las frases renderizadas y se espera a
que el usuario realice un evento. Si el evento resulta ser oprimir una tecla y esa tecla es
RETURN o ENTER, entonces el ciclo se rompe con la instrucción break y se termina la
función retornando la ventana principal del programa.
Figura 7.2: Saludo Inicial en el juego Ahorcado
Una ventana en el sistema pygame es una superficie (surface en inglés) que sirve para
almacenar imágenes. Dichas imágenes deben ser transferidas a la superficie como mapas
de bits (de allı́ que el texto deba ser renderizado para poder ser mostrado, como se mencionó anteriormente). La posición donde se quiere transferir la imagen es una coordenada
(x, y) donde los valores de x y y van de (0, 0) (la esquina superior izquierda) a (w, h), la
92
7.1 Listas
esquina inferior derecha. En el cuadro 7.4 pueden detallarse dos operaciones de superficies
en pygame.
FT
def saludoInicial():
"Funcion que inicializa el sistema grafico"
"y muestra la ventana inicial"
# Inicializa el sistema
pygame.init()
ventana = pygame.display.set_mode((640, 480))
# Selecciona el tipo de fuente
fuente = pygame.font.SysFont("arial", 30)
# Construye las frases
titulo = fuente.render("JUEGO AHORCADO", True, (0,0,0))
subtitulo = fuente.render("Presione enter para empezar",
True,(0,0,0))
DR
A
# Ciclo para que el usuario lea el saludo de inicio
presionaEnter = False
while True:
# Muestra la informacion
ventana.fill((255,255,255))
ventana.blit(titulo,(180,180))
ventana.blit(subtitulo,(140,240))
# Maneja el evento de presionar una tecla
for e in pygame.event.get():
if e.type == pygame.KEYDOWN:
if e.key == pygame.K_RETURN:
presionaEnter = True
if presionaEnter:
break
# Actualiza el sistema
pygame.display.update()
return ventana
Algoritmo 7.2: Pantalla de inicio del juego ahorcado
Por otro lado, los eventos que ocurren en un programa de pygame tienen un tipo y
una llave (o nombre). El tipo de los eventos identifica la acción que el usuario realiza,
por ejemplo, el tipo QUIT para salir, KEYDOWN y KEYUP para presionar o soltar un botón
del teclado, y MOUSEMOTION, MOUSEBUTTONUP y MOUSEBUTTONDOWN para mover el mouse,
93
7 Noción de Abstracción de Datos
size(t)
set underline(b)
set bold(b)
set italic(b)
Acción
Crea una nueva superficie donde se imprime el texto t con
color c (una tipleta que representa el color en formato RGB).
El argumento a es un booleano que especifica si el texto
llevará antialias
Retorna las dimensiones necesarias (ancho,alto) para imprimir el texto t
De acuerdo al argumento booleano b, subraya el texto a
imprimir
De acuerdo al argumento booleano b, pone en negrilla el
texto a imprimir
De acuerdo al argumento booleano b, pone el texto a imprimir en itálica
FT
Operación
render(t,a,c)
Cuadro 7.3: Operaciones básicas del módulo de fuentes en el sistema Pygame
Acción
Dibuja la imagen s en la posición d de la superficie
Llena la superficie con el color c
DR
A
Operación
blit(s,d)
fill(c)
Cuadro 7.4: Operaciones básicas del módulo de superficies en el sistema Pygame
Ciclo for-each
presionar un botón o soltarlo. La llave del tipo determina exactamente la fuente del evento,
por ejemplo, K RETURN para la tecla RETURN o ENTER del teclado, K A para la tecla A,
y ası́ sucesivamente.
Lo eventos que van sucediendo son almacenados temporalmente en una lista, la cual
es retornada por la función pygame.event.get(). Esta lista puede recorrerse, es decir,
conocer sus elementos, usando un ciclo while, sin embargo, cómo se dijo en el capı́tulo 6,
existe otro tipo de ciclo que realiza iteraciones sobre los elementos de una lista, llamado
ciclo for-each . Este tipo de ciclo tiene dos particularidades: (1) en cada iteración una
variable definida en el ciclo toma el valor de un elemento de la lista en el orden en que
se encuentran los elementos en la lista, y (2) no se tienen que manejar los ı́ndices de
los elementos de la lista. Estas caracterı́sticas hacen valioso este tipo de ciclo ya que el
programador no se preocupa por los ı́ndices de la lista los cuales pueden llevar fácilmente
a un error en el programa (e.g. tratar de acceder un elemento inexistente).
El procedimiento dibujarTablero() que se muestra en el algoritmo 7.3, tiene como
parámetros la ventana donde se dibujará, la palabra secreta y las listas de letras acertadas
y letras falladas. Como el tamaño de las letras que se van encontrando de la palabra secreta y el tamaño de las letras falladas son distintos, primero se crean dos fuentes. Luego se
94
7.1 Listas
FT
def dibujarTablero(ventana, palabraSecreta, letrasAcertadas,
letrasFalladas):
"Procedimiento que dibuja/actualiza el tablero del juego"
# Selecciona los tipos de fuente
fuente1 = pygame.font.SysFont("arial", 35)
fuente2 = pygame.font.SysFont("arial", 25)
# Crea la frase que va a mostrar dadas las letras acertadas
palabraAMostrar = ""
for letra in palabraSecreta:
if letra in letrasAcertadas:
palabraAMostrar = palabraAMostrar + \
string.capitalize(letra) + " "
else:
palabraAMostrar = palabraAMostrar + "_" + " "
# Borra completamente la ventana
ventana.fill((255,255,255))
DR
A
# Dibuja el estado del ahorcado dadas las letras falladas
if len(letrasFalladas) > 0:
ventana.blit(pygame.image.load(os.path.join("ahorcado" + \
str(len(letrasFalladas)) + \
".jpg")),(80,90))
# Muestra la frase "Letras Falladas"
ventana.blit(fuente2.render("Letras Falladas:",True,(0,0,0)), \
(330,100))
# Muestra las letras falladas
i=0
if letra in letrasFalladas:
ventana.blit(fuente2.render(string.capitalize(letra),True, \
(0,0,0)),(330+i,150))
i = i + 30
# Dibuja la frase actual
ventana.blit(fuente1.render(palabraAMostrar,True,(0,0,0)), \
(100,380))
# Actualiza el sistema
pygame.display.update()
Algoritmo 7.3: Dibuja/Actualiza la pantalla principal del juego ahorcado
95
7 Noción de Abstracción de Datos
(a)
(b)
(c)
(d)
FT
construye la palabra que se va a mostrar recorriendo cada una de las letras de la palabra
secreta y adicionándolas (en mayúscula) a una cadena de caracteres si la letra se encuentra
en la lista de letras acertadas. Si la letra no se encuentra en la lista entonces se adiciona una lı́nea de subrayado. Acto seguido se limpia la pantalla y se dibuja el estado del
ahorcado. Este estado es dibujado cargando una imagen previamente hecha cuyo nombre
es ahorcadoX.jpg donde X es un número entre 1 y 10 (estas imágenes, que pueden verse
en la figura 7.3, se encuentran como archivos en el sistema operativo y son cargadas en
el programa por medio del módulo de rutas de archivos del sistema os cuyas operaciones
básicas pueden verse en el cuadro 7.54 ). Después se muestran las letras fallas y el estado
actual de la palabra secreta. Por último se actualiza el sistema.
(e)
(f)
(g)
(h)
(i)
(j)
DR
A
Figura 7.3: Etapas del ahorcado
Operación
path.exists(p)
path.basename(p)
path.dirname(p)
path.join(p1,p2,p3,...)
Acción
Retorna true si la ruta p existe, false de lo contrario
Retorna el nombre base de la ruta p (e.g. si
el sistema operativo actual es linux y p es
/usr/local/bin/programa entonces el resultado de
aplicar esta función es programa)
Retorna el nombre del directorio de la ruta p (e.g.
si el sistema operativo actual es windows y p es
C:\windows\temp\programa entonces el resultado de
aplicar esta función es C:\windows\temp)
Junta las rutas de archivos p1,p2,... de manera adecuada (e.g. si el sistema operativo actual es windows,
p1 es C: y p2 es temp, entonces el resultado de aplicar
esta función es C:\temp)
Cuadro 7.5: Operaciones básicas del módulo de rutas de archivos del sistema operativo
4
En el capı́tulo ?? se profundizará un poco en el sistema os y se usará el módulo de manejo de archivos
y directorios del sistema operativo.
96
7.1 Listas
FT
Las letras que el jugador quiere probar en el juego las solicita simplemente presionando la
tecla correspondiente. En el algoritmo 7.4 se muestra el proceso para hacer esto. Se define
un ciclo infinito para esperar indefinidamente hasta que el usuario realice algún evento. Si
el evento realizado es presionar una tecla, se verifica si esa tecla corresponde a una letra y
si esto es cierto entonces se retorna la letra como una cadena de caracteres. De lo contrario,
es decir si la tecla no es una letra, hacemos la aplicación de la operación para interpretar
un sonido, que en este caso es un archivo de tipo wav que contiene un beep.
DR
A
def pedirLetra(ventana):
"Funcion que retorna la letra que el usuario ha ingresado"
# Ciclo para que el usuario ingrese la letra
while True:
for e in pygame.event.get():
if e.type == pygame.KEYDOWN:
# Si presiona una tecla que corresponde a una letra
if e.key == pygame.K_a:
return "a"
if e.key == pygame.K_b:
return "b"
if e.key == pygame.K_c:
return "c"
# ... aqui van los condicionales para las demas letras
if e.key == pygame.K_x:
return "x"
if e.key == pygame.K_y:
return "y"
if e.key == pygame.K_z:
return "z"
# Si presiona una tecla que no es una letra suena beep
else:
pygame.mixer.music.load("beep.wav")
pygame.mixer.music.play()
# Actualiza el sistema
pygame.display.update()
Algoritmo 7.4: Retorna la letra que el usuario presione en el juego ahorcado
Finalmente el algoritmo 7.5 para acabar el juego simplemente dibuja dos rectángulos
rellenos en la ventana y escribe en ellos las frases de ganador o perdedor. Mientras tanto
espera a que el jugador presione alguna tecla y cuando esto ocurre termina el sistema. Un
97
7 Noción de Abstracción de Datos
ejemplo del juego con los dos posibles finales puede verse en la figura 7.4.
FT
def acabarJuego(ventana, resultado):
"Procedimiento que termina el juego ahorcado"
# Selecciona la fuente y construye las frases finales
fuente = pygame.font.SysFont("arial", 40)
gano = fuente.render("Gano :-)", True, (255,0,0))
perdio = fuente.render("Perdio :-(", True, (255,0,0))
DR
A
# Ciclo para que el usuario vea el resultado y termine
acabo = False
while True:
# Si gano
if resultado == True:
pygame.draw.rect(ventana,(255,0,0),(335,240,215,85),5)
ventana.blit(gano,(355,260))
# Si perdio
else:
pygame.draw.rect(ventana,(255,0,0),(335,240,240,85),5)
ventana.blit(perdio,(355,260))
# Revisa los eventos que suceden
for e in pygame.event.get():
if e.type == KEYDOWN:
acabo = False
# Actualiza el sistema
pygame.display.update()
# Si presiono una tecla termina el sistema
if acabo:
pygame.quit()
break
Algoritmo 7.5: Termina el juego ahorcado
? ? ?
Ejemplo 7.2
Supongamos que queremos crear un juego que simule las elecciones para presidente. El
juego debe recibir el voto de cada uno de los n ciudadanos del paı́s y luego contar el
número de votos para cada candidato de manera que se sepa quién es el presidente electo.
La tarjeta o tarjetón electoral es un documento donde se encuentra la lista de candidatos
y el voto el blanco. Para votar, un ciudadano simplemente marca alguno de los candidatos
o la casilla del voto en blanco. Cuando se realiza el escrutinio, se cuentan cuántos votos se
marcaron para cada candidato y el que haya sacado la mayor cantidad es el ganador.
La información anterior provee los datos necesarios para construir el algoritmo 7.6 el
98
(a) Ganó el juego ahorcado
FT
7.1 Listas
(b) Perdió el juego ahorcado
Figura 7.4: Estados finales del juego ahorcado
DR
A
cual simula las elecciones. Se tienen dos listas: la lista de los nombres de los candidatos y la
lista de los votos. En la lista de votos se irán contabilizando los votos que cada candidato
obtenga. Las listas listaNombres y listaVotos son correspondientes, es decir, el candidato
1, el cual es el elemento 1 de listaNombres, tiene el número de votos del primer elemento
de listaVotos, el número de votos del candidato 2 (elemento 2 de la lista) es el número
que se encuentra en la segunda posición de la lista de votos, y ası́ sucesivamente. Es de
notarse que en la lista de candidatos se tiene como último elemento “voto nulo”, esto es
necesario para contabilizar este tipo de voto aunque no sea un candidato como tal. La
posición donde se encuentra el voto nulo se almacena en la variable posVotoNulo para su
uso en la contabilidad de dicho voto.
La ventana se crea en la función comienzoElecciones(), la cual se deja como ejercicio
para el lector.
El ciclo para hacer las votaciones hace n iteraciones, siendo n un parámetro del procedimiento. En cada iteración se obtiene el nombre del candidato por el que se vota mediante la
aplicación de la función sufragar(). Este nombre retornado por sufragar() se busca en
listaNombres y si existe se le agrega un voto a su elemento correspondiente. Si el nombre
no existe en la lista, entonces se contabiliza en el último elemento de la lista de votos,
haciendo entender que fue un voto nulo.
Una vez termina el ciclo, se debe ordenar la lista de acuerdo a los votos que recibieron
cada uno de los candidatos. Esto se hace en la función ordenar(). Luego de esta aplicación,
en la primera posición de listaNombres queda el nombre del ganador de las elecciones,
el cual es mostrado en el procedimiento mostrarGanador(), que también se deja como
99
7 Noción de Abstracción de Datos
ejercicio para el lector.
FT
def elecciones(n):
"Procedimiento para simular unas elecciones de presidente"
listaNombres = ["candidato1", "candidato2", "candidato3",
"candidato4", "candidato5", "en blanco",
"voto nulo"]
listaVotos = [0, 0, 0, 0, 0, 0, 0]
posVotoNulo = len(listaNombres) - 1
# Dibuja la tarjeta electoral
ventana = comienzoElecciones()
DR
A
# Comienzan las votaciones: Ciclo de n iteraciones
i = 1
while i < n:
# Se obtiene el nombre del candidato por el que se vota
voto = sufragar(ventana, listaNombres)
# Se busca el nombre dado en la lista de candidatos
# y se le agrega un voto
j = 0
while j < len(listaNombres) - 1:
if voto == listaNombres[j]:
listaVotos[j] = listaVotos[j] + 1
break
j = j + 1
# Si el nombre no esta en la lista es un voto nulo
if j == len(listaNombres):
listaVotos[posVotoNulo] = listaVotos[posVotoNulo] + 1
i = i + 1
# Escrutinio: se ordena la lista de candidatos por orden de votos
listaNombres = ordenar(listaNombres, listaVotos)
# Resultado
mostrarGanador(ventana, listaNombres, listaVotos)
Algoritmo 7.6: Simulador de elecciones
La función sufragar() (algoritmo 7.7) recibe como parámetros la ventana donde se
harán las votaciones y la lista de candidatos. En ella se declara una variable donde se
almacenará el nombre del candidato elegido y luego, en un ciclo infinito, se maneja el
evento de presionar un botón del mouse. Cuando este evento sucede se obtiene la posición
donde se hizo clic y de acuerdo a ella se determina el candidato por el cual se quiere votar.
Una vez se haya hecho clic, el ciclo se interrumpe y se retorna el candidato elegido. Si
100
7.1 Listas
la acción de hacer clic se hace fuera de los rectángulos que limitan las imágenes de los
candidatos, se considera que el voto fue nulo y la variable elegido es retornada con su
valor por defecto, es decir, una cadena vacı́a.
FT
def sufragar(ventana, listaNombres):
"Funcion que retorna el candidato por el cual se ha votado"
# Declaracion de la variable que tendrá el nombre del candidato
elegido = ""
DR
A
# Comienzan las votaciones: Ciclo de n iteraciones
haceClic = False
while True:
# Maneja el evento de hacer clic
for e in pygame.event.get():
if e.type == pygame.MOUSEBUTTONDOWN:
haceClic = True
pos = pygame.mouse.get_pos()
if pos[0] >= 22 and pos[0] <= 122 and \
pos[1] >= 80 and pos[1] <= 200:
elegido = listaNombres[0]
if pos[0] >= 142 and pos[0] <= 242 and \
pos[1] >= 80 and pos[1] <= 200:
elegido = listaNombres[1]
if pos[0] >= 262 and pos[0] <= 362 and \
pos[1] >= 80 and pos[1] <= 200:
elegido = listaNombres[2]
if pos[0] >= 382 and pos[0] <= 482 and \
pos[1] >= 80 and pos[1] <= 200:
elegido = listaNombres[3]
if pos[0] >= 502 and pos[0] <= 602 and \
pos[1] >= 80 and pos[1] <= 200:
elegido = listaNombres[4]
if pos[0] >= 622 and pos[0] <= 722 and \
pos[1] >= 80 and pos[1] <= 200:
elegido = listaNombres[5]
if haceClic:
break
# Actualiza el sistema
pygame.display.update()
return elegido
Algoritmo 7.7: Retorna un candidato en el juego de elecciones
El algoritmo 7.8 ordena las listas de candidatos y votos por número de votos obtenidos.
101
7 Noción de Abstracción de Datos
FT
Esto lo logra realizando dos ciclos anidados. El ciclo externo recorre las listas desde el
primer elemento hasta el último, encontrando el menor elemento y ubicándolo en la posición adecuada según el orden que se desea. El menor elemento se encuentra realizando el
ciclo interno, desde la posición donde se encuentra el recorrido de las listas hasta el final,
buscando saber cuál es la posición del elemento con menos valor.
def ordenar(listaNombres, listaVotos):
"Funcion que ordena las listas por numero de votos"
# Ciclo que recorre las listas
contador1 = 0
while contador1 < len(listaNombres):
contador2 = contador1
posMenor = contador1
# Ciclo que encuentra la posicion del elemento menor
while contador2 < len(listaNombres):
if listaVotos[posMenor] > listaVotos[contador2]:
posMenor = contador2
contador2 = contador2 + 1
DR
A
# Ubica el menor en la posicion adecuada según el orden
nombreTemp = listaNombres.pop(posMenor)
listaNombres.insert(contador1, nombreTemp)
votoTemp = listaVotos.pop(posMenor)
listaVotos.insert(contador1, votoTemp)
contador1 = contador1 + 1
return listaNombres,listaVotos
Algoritmo 7.8: Ordena las listas de candidato y votos en el juego de elecciones
Ordenamiento
Matriz
? ? ?
Ordenar una lista es organizar cada elemento de ella en un orden particular. En el
algoritmo 7.8 se utilizó el método Selection Sort, el cual encuentra el mı́nimo valor en la
lista, lo intercambia por el valor de la primera posición y repite este proceso en el resto
de la lista (empezando en la segunda posición y avanzando una posición cada iteración).
Existen muchos otros algoritmos para ordenar una lista. Se deja como ejercicio para el
lector investigar e implementar algunos de esos algoritmos.
Los elementos que tienen las listas pueden ser de cualquier tipo de datos. Esto significa
que los elementos podrı́an ser también listas. Cuando se tiene una lista de listas se dice
que se tiene una matriz . La cantidad de niveles de anidamiento de las listas determina el
102
7.1 Listas
número de dimensiones que tiene la matriz. En el ejemplo 7.3 se trabajará con listas de
listas, es decir, matrices de dos dimensiones.
DR
A
FT
Ejemplo 7.3
Buscaminas es un juego muy popular cuyo objetivo es “limpiar” un campo minado sin
detonar ninguna mina. El campo minado es una grilla de n × m ubicaciones, en las cuales
puede o no haber una mina.
Este es un juego de un solo jugador, quien debe explorar el campo minado haciendo
clic en las ubicaciones de manera estratégica para no detonar una mina. Cuando se limpia
(se hace clic en) una ubicación que no tiene una mina, esta revela una pista acerca de las
ubicaciones adyacentes. La pista es un número, el cual hace referencia a la cantidad de
minas que hay alrededor de dicha ubicación.
El juego termina cuando se hace clic en una mina ó cuando se ha limpiado la totalidad
de ubicaciones que no tienen mina. En la figura 7.5 puede verse un ejemplo del buscaminas
para Windows 7.
Figura 7.5: Buscaminas en Windows 7
El procedimiento para jugar buscaminas se encuentra en el algoritmo 7.9. La idea detrás
de este procedimiento es contar con dos matrices, una (tableroOculto) en la que se encuentra el tablero completo, es decir, se conoce plenamente la ubicación de las minas y,
103
7 Noción de Abstracción de Datos
por lo tanto, las pistas. La otra matriz (tableroVisible) representa el tablero tal y como
se ve en el juego, por lo que inicia vacı́a y a medida que se escoge una ubicación, se va
revelando el contenido del tablero.
FT
def buscaminas(ancho, alto, numMinas):
"Procedimiento para jugar buscaminas"
tableroVisible = construirMatriz(ancho, alto)
tableroOculto = llenarTablero(ancho, alto, numMinas)
juegoAcabado = False
# Dibuja la ventana inicial
ventana = saludoInicial()
# Ciclo del juego
while not juegoAcabado:
# Dibuja/Actualiza el tablero
dibujarTablero(ventana, tableroVisible)
# Pide hacer clic en una posicion
x,y = obtenerUbicacion(ventana)
DR
A
# Procede de acuerdo a la ubicacion
tableroVisible[x][y] = tableroOculto[x][y]
# Si detono una mina (perdio)
if tableroOculto[x][y] == 'M':
acabarJuego(ventana, False)
juegoAcabado = True
else:
# Si no detono una mina pero completo el tablero (gano)
if tableroLleno(tableroVisible):
acabarJuego(ventana, True)
juegoAcabado = True
Algoritmo 7.9: Juego buscaminas
La parte gráfica de este algoritmo se maneja de manera similar al algoritmo 7.1 del ejemplo del juego ahorcado, simplemente cambian algunos parámetros e implementaciones de las
funciones y procedimientos saludoInicial(), dibujarTablero(), obtenerUbicacion()
(que en el ahorcado se llamaba pedirLetra()) y acabarJuego(). El proceso para obtener
el dato ingresado por el usuario es, quizás, el que más cambia dado que ahora dicho dato es
una coordenada que representa la ubicación que quiere explorar en el tablero. Todas estas
funciones se dejan como ejercicio para implementar.
Para trabajar con el tablero primero debe construirse la matriz. El proceso es bastante
simple y puede verse en el algoritmo 7.10. Se tienen dos ciclos anidados, el primero se
104
7.1 Listas
encarga de crear las sublistas y el segundo de ingresar la cantidad apropiada de elementos
a cada subsista. A medida que las sublistas van quedando construidas, se van adicionando
una lista inicialmente vacı́a, creando ası́ la matriz, que es retornada al final.
for i in range(alto):
listatemp = []
for j in range(ancho):
listatemp.append(' ')
matriz.append(temp)
return matriz
FT
def construirMatriz(ancho, alto):
"Funcion que crea e inicializa con ' ' una matriz de anchoxalto"
matriz = []
Algoritmo 7.10: Crea y retorna una matriz de dimensiones ancho × alto
DR
A
Una vez el tablero ha sido construido, se debe llenar con las minas y pistas. Este proceso
se realiza en el algoritmo 7.11. Primero se crea la matriz que representa el tablero. Luego
esta matriz se empieza a llenar con las minas (sı́mbolo ’M’). Las posiciones de las minas
son halladas de manera aleatoria y poniendo mucho cuidado de no repetir ninguna.
La forma de hallar y poner las pistas es relativamente simple: se recorre la matriz un
elemento a la vez y en cada ubicación se pregunta si dicha ubicación contiene una mina.
Si esto es cierto, entonces se continua con la siguiente ubicación, pero si es falso entonces
se revisa cada uno de los ocho lugares adyacentes a la ubicación actual preguntando por
una mina. Cada vez que una mina sea encontrada en una posición adyacente, una variable
pista es aumentada una unidad en su valor, que inicialmente es cero. Ası́, si se tienen tres
minas alrededor, por ejemplo, entonces el valor de la variable terminará siendo tres y ese
número irá en la ubicación correspondiente de la matriz.
Si el lector pone mucha atención en la parte de las pistas del algoritmo 7.11 puede
darse cuenta que hay problemas en ella. Supongamos que estamos en la posición (0,0)
de la matriz, es decir, recién iniciaron los dos ciclos, y en ella no hay una mina. Como
este lugar en la matriz es la esquina superior izquierda, esto quiere decir que hay que
revisar en las posiciones (0,1), (1,1) y (1,0), que son las únicas ubicaciones adyacentes a
(0,0). Sin embargo, nótese que en el algoritmo la revisión de minas se hace sobre ocho
ubicaciones adyacentes, luego ¿qué va a pasar en las cinco posiciones inexistentes que se
están revisando? Sale un error porque efectivamente no existen. Entonces hay que modificar
105
7 Noción de Abstracción de Datos
el algoritmo para evitar estos problemas en los bordes de la matriz.
FT
def llenarTablero(ancho, alto, numMinas):
"Funcion que llena el tablero del buscaminas con minas y pistas"
# Primero se crea la matriz que servira de tablero
tableroOculto = construirMatriz(ancho, alto)
# Se llena el tablero con una cantidad numMinas de minas ('M')
i = 0
while i < numMinas:
dirx = random.randint(0, ancho - 1)
diry = random.randint(0, alto - 1)
if tableroOculto[dirx][diry] != 'M':
tableroOculto[dirx][diry] = 'M'
i = i + 1
DR
A
# Se recorre el tablero poniendo las pistas
for i in range(alto):
for j in range(ancho):
if tableroOculto[i][j] != 'M':
pista = 0
if tableroOculto[i+1][j] == 'M':
pista = pista + 1
if tableroOculto[i-1][j] == 'M':
pista = pista + 1
if tableroOculto[i][j+1] == 'M':
pista = pista + 1
if tableroOculto[i][j-1] == 'M':
pista = pista + 1
if tableroOculto[i+1][j+1] == 'M':
pista = pista + 1
if tableroOculto[i+1][j-1] == 'M':
pista = pista + 1
if tableroOculto[i-1][j+1] == 'M':
pista = pista + 1
if tableroOculto[i-1][j-1] == 'M':
pista = pista + 1
tableroOculto[i][j] = pista
return tableroOculto
Algoritmo 7.11: Llena el tablero del buscaminas con minas y pistas
El algoritmo 7.12 es una modificación de la parte de las pistas del algoritmo 7.11. En él
106
7.1 Listas
antes de revisar la ubicación se pregunta si dicha ubicación existe en la matriz.
DR
A
FT
# Se recorre el tablero poniendo las pistas
for i in range(alto):
for j in range(ancho):
if tableroOculto[i][j] != 'M':
pista = 0
if i < alto - 1:
if tableroOculto[i+1][j] == 'M':
pista = pista + 1
if i > 0:
if tableroOculto[i-1][j] == 'M':
pista = pista + 1
if j < ancho - 1:
if tableroOculto[i][j+1] == 'M':
pista = pista + 1
if j > 0:
if tableroOculto[i][j-1] == 'M':
pista = pista + 1
if i < alto - 1 and j < ancho - 1:
if tableroOculto[i+1][j+1] == 'M':
pista = pista + 1
if i < alto - 1 and j > 0:
if tableroOculto[i+1][j-1] == 'M':
pista = pista + 1
if i > 0 and j < ancho - 1:
if tableroOculto[i-1][j+1] == 'M':
pista = pista + 1
if i > 0 and j > 0:
if tableroOculto[i-1][j-1] == 'M':
pista = pista + 1
tableroOculto[i][j] = pista
Algoritmo 7.12: Modificación del algoritmo para llenar el tablero del buscaminas con
pistas
En el juego, para saber si el éste acabó se deben realizar dos tareas: preguntar si en la
ubicación que el jugador escogió hay una mina y revisar si todo el tablero ha sido explorado. La primera tarea es muy sencilla de hacer, solo se pregunta si en la ubicación actual
hay un caracter ’M’. La segunda tarea requiere hacer un recorrido por todo la matriz
tableroVisible buscando una ubicación que tenga el valor inicial ’ ’ y cuya ubicación
correspondiente en tableroOculto no tenga una mina. Si no existe dicha ubicación, entonces se hay llenado todo el tablero y el jugador ganó. El algoritmo 7.13 muestra esta
107
7 Noción de Abstracción de Datos
segunda tarea.
FT
def tableroLleno(tableroVisible, tableroOculto):
"Funcion que revisa si se han descubierto todas las ubicaciones"
"sin mina"
lleno = True
for i in range(len(tableroVisible)):
for j in range(len(tableroVisible[0])):
if tableroVisible[i][j] == ' ' and \
tableroOculto[i][j] != 'M':
lleno = False
return lleno
Algoritmo 7.13: Función que determina si se han descubierto todas las ubicaciones que
no tienen mina
? ? ?
Ejercicios
DR
A
7.2.
7.1 La operación in para listas, revisa si un elemento se encuentra en una lista. Ası́, si
escribimos if letra in letrasFalladas, lo que queremos saber es si el elemento
letra se encuentra en la lista letrasFalladas.
Desarrolle, sin usar dicha operación in, la función buscarElemento() que tome como
argumentos una lista y un elemento, y retorne True si el elemento efectivamente se
encuentre en la lista, y False de lo contrario.
7.2 En el juego Ahorcado visto en este capı́tulo se pueden repetir las letras falladas y
esto hace que se acumule la misma letra en la lista de letras falladas y, por lo tanto,
se dibuje un elemento más del ahorcado. Corrija esto haciendo que el programa
muestre una aviso al jugador diciendo, cuando se repite una letra fallada, que ya se
escogió dicha letra y la pida de nuevo sin anexarla de nuevo a la lista y sin dibujar
un elemento más del ahorcado.
7.3 La última letra que se presiona y el dibujo completo en el juego ahorcado no se
alcanza a mostrar cuando termina el juego. Modifique los algoritmos necesarios para
que efectivamente se muestre la última letra presionada y se dibuje completamente
el ahorcado (cuando pierde).
7.4 Complete el ejemplo 7.2 de las elecciones desarrollando la función comienzoElecciones()
y el procedimiento mostrarGanador(). Para que los algoritmos aquı́ mostrados fun-
108
7.2 Ejercicios
FT
cionen correctamente, la ventana creada y retornada en comienzoElecciones() debe
tener unas dimensiones de 750 × 350 y verse como la figura 7.6.
DR
A
Figura 7.6: Ventana del juego de las elecciones
Es muy importante que en la ventana creada en comienzoElecciones() las fotos
de los candidatos estén en unos cuadros de tamaño 100 × 120 y las posiciones de
sus esquinas superior-izquierda sean: (22,80), (142,80), (262,80), (382,80), (502,80),
y (622,80).
7.5 La función ordenamiento del ejemplo 7.2 retorna las listas en orden ascendente, es
decir, de menor a mayor, de acuerdo a los votos obtenidos. Desarrolle la función
invertirLista() para tomar estas listas y retornarlas en orden invertido (i.e. de
mayor a menor).
7.6 Investigue e implemente en el juego de las elecciones los siguientes métodos de ordenamiento: Bubble Sort, Insertion Sort y Shell Sort.
7.7 Desarrolle todas las funciones y procedimientos gráficos del juego buscaminas.
7.8 El juego triqui del ejemplo 6.1 puede desarrollarse con una matriz y funciones de
pygame. Modifique las funciones necesarias para hacerlo.
109
DR
A
FT
7 Noción de Abstracción de Datos
110
FT
Bibliografı́a
[1] Jean-Raymond Abrial. Guidelines to formal system studies. MATISSE project, November 2000.
[2] Donald E. Knuth. Structured programming with go to statements. ACM Computing
Surveys, 6(4):261–301, December 1974.
[3] Guido Van Rossum and Fred L Drake Jr. An Introduction to Python. Network Theory
Ltd, 2011.
[4] Guido Van Rossum and Fred L Drake Jr. The Python Language Reference Manual.
Network Theory Ltd, 2011.
DR
A
[5] Gerardo Sarria. Introduction to programming for engineers following the parachute
paradigm. In 39th ASEE/IEEE Frontiers in Education. IEEE, San Antonio, TX, USA,
18–21 October 2009.
[6] G. Michael Schneider. The introductory programming course in computer science: ten
principles. In Papers of the SIGCSE/CSA technical symposium on Computer science
education, SIGCSE ’78, pages 107–114, New York, NY, USA, 1978. ACM.
111
Descargar