´ lica de Chile Pontificia Universidad Universidad Cat Catolica o Chile ´n Depar Depart tamento de Ciencia de la Computaci Computaci on o Escuela de Ingenier´ ıa
Apuntes del Curso iic1103 Introducci´ on a la Programaci´ on on on con Python
Auto Autorr
Adri Adri´ an a ´n Soto Suarez Mauricio Mauric io Arriagada-Be Arriag ada-Ben n´ıtez Marzo 2015
´ Indice general 1. Pr´ Pro ´logo
3
2. Conceptos previos 2.1. Introducc Introducci´ i´on a los algoritmos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.2. Creando un nuevo proyecto en Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4 4 6
3. Tipos de datos, expresiones 3.1. Tipos de datos . . . . . . 3.2.. Comand 3.2 Comandos os B´ Ba´sicos . . . . 3.2.1. Operadores . . . . 3.3.. Progra 3.3 Programas mas b´ asicos . . . . 3.4. If, elif y else . . . . . . . . 3.5. Loops . . . . . . . . . . . 3.5.1. While . . . . . . . 3.5.2. For . . . . . . . . . 3.5.3. Break y continue .
y control de flujo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
8 8 9 10 11 12 15 15 16 17
4. Funcion unciones es y m´ odulos 19 4.1. Funciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 4.2. 4.2. M´ odulos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20 4.3. Main . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 5. Strings 23 5.1.. Declar 5.1 Declaraci aci´ o´n y manejo de strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 5.2. Funciones de strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 5.3. El tipo chr y la tabla ASCII . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26 6. Listas 6.1. Listas Unidimensionales . . . . . . . . . . . . . . . 6.2 6.2. Util Utilid idad ades es y fun funccione ioness par para lis lista tass unid unidim imen ensi sion onaales les 6.3. For . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.4. Ordenamiento . . . . . . . . . . . . . . . . . . . . . 6.5. Listas bidimensionales . . . . . . . . . . . . . . . . 6.6. Valores por referencia . . . . . . . . . . . . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
28 28 30 32 33 33 34
7. Diccionarios 36 7.1. Funcionamiento de un diccionario . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36 7.2. Uso del diccionario . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
1
´ Indice general 1. Pr´ Pro ´logo
3
2. Conceptos previos 2.1. Introducc Introducci´ i´on a los algoritmos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.2. Creando un nuevo proyecto en Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4 4 6
3. Tipos de datos, expresiones 3.1. Tipos de datos . . . . . . 3.2.. Comand 3.2 Comandos os B´ Ba´sicos . . . . 3.2.1. Operadores . . . . 3.3.. Progra 3.3 Programas mas b´ asicos . . . . 3.4. If, elif y else . . . . . . . . 3.5. Loops . . . . . . . . . . . 3.5.1. While . . . . . . . 3.5.2. For . . . . . . . . . 3.5.3. Break y continue .
y control de flujo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
8 8 9 10 11 12 15 15 16 17
4. Funcion unciones es y m´ odulos 19 4.1. Funciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 4.2. 4.2. M´ odulos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20 4.3. Main . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 5. Strings 23 5.1.. Declar 5.1 Declaraci aci´ o´n y manejo de strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 5.2. Funciones de strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 5.3. El tipo chr y la tabla ASCII . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26 6. Listas 6.1. Listas Unidimensionales . . . . . . . . . . . . . . . 6.2 6.2. Util Utilid idad ades es y fun funccione ioness par para lis lista tass unid unidim imen ensi sion onaales les 6.3. For . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.4. Ordenamiento . . . . . . . . . . . . . . . . . . . . . 6.5. Listas bidimensionales . . . . . . . . . . . . . . . . 6.6. Valores por referencia . . . . . . . . . . . . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
28 28 30 32 33 33 34
7. Diccionarios 36 7.1. Funcionamiento de un diccionario . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36 7.2. Uso del diccionario . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
1
8. Clases 8.1. Programac Programaci´ i´on orientada a ob je jetos . . . . . . 8.2. Crear una clase . . . . . . . . . . . . . . . . 8.2.1. Declarar una clase . . . . . . . . . . 8.2.2. Atributos de la clase . . . . . . . . . 8.2.3. Constructor . . . . . . . . . . . . . . 8.2.4. Instanciar un obje bjeto en el programa 8.2.5. Self . . . . . . . . . . . . . . . . . . 8.2.6. M´etodos . . . . . . . . . . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
39 . 39 . 39 . 39 . 39 . 40 . 41 . 42 . 42
9. Archivos 9.1. ¿Por qu´e guardar datos? 9.2. Ruta de un archivo . . . 9.3. Leer un archivo de texto 9.4. Escribir un archivo .txt 9.4.1. Modo write . . . 9.4.2. Modo append . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
45 45 45 45 46 46 47
. . . . .
48 48 48 48 49 50
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
10.Recursi´ on 10.1. Definir Definir una funci´ funcio´n recursiva . . 10.2. Ejemplos de funciones recursivas 10.2.1. Quicksort . . . . . . . . . 10.2.2. Permutaci´on de Strings . 10.2.3. Mergesort . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
11.Simulaci´ on 53 11.1. ¿Para qu´e simular? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53 11.2. Ejemplos de simulaci´on . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53 11.2.1. Ataque Zombie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53 12.Ejercicios 55 12.1. Cola de supermercado . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55 12.2. Banco de la Plaza . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57 12.3. Algebraco . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64
2
Cap´ıtulo 1
Pr´ ologo Este documento tiene como objetivo resumir los contenidos del curso IIC1103 Introducci´ on a la Programaci´ on dictado el segundo semestre del a˜no 2013. Su objetivo no es de ninguna forma reemplazar la asistencia a clases o laboratorios. Tampoco tiene como fin ser la ´unica fuente de estudio para el alumno, puesto que los contenidos son lo suficientemente amplios como para requerir bastante tiempo para lograr dominarlos en profundidad. Se recomienda fuertemente al lector complementar los contenidos del documento con ejercitaci´on de su parte. Esta puede ser rehacer las tareas planteadas durante el semestre, los laboratorios o incluso ejercicios propuestos de internet. Tambi´ en es importante recordarle al alumno que este texto fue realizado por otro ser humano, por lo que puede contener errores menores. Sin embargo, todo el c´odigo utilizado aqu´ı ha sido previamente testeado. Cualquier feedback o cr´ıtica puede ser enviada al mail
[email protected] . Para finalizar, es necesario recordarle al lector que la mejor forma de preparar una evaluaci´on en este curso es programar, ya que el lector debe ser capaz de resolver por sus propios medios los problemas que requieran de la modelaci´on y posterior desarrollo de un algoritmo.
1
Desear´ıa aprovechar este espacio para agradecer a Esteban Andr´es Salgado por regalarme su p ortada =).
3
Cap´ıtulo 2
Conceptos previos 2.1.
Introducci´ on a los algoritmos
Antes de comenzar a programar debemos comprender el concepto de algoritmo. Un algoritmo es un conjunto finito de pasos definidos y ordenados que nos permiten realizar una actividad de manera met´odica. Veamos un ejemplo b´asico de algoritmo. Ejemplo 2.1 Dise˜ ne un algoritmo que decida cargar un tel´ efono celular si le queda poca bater´ıa.
Figura 2.1: algoritmo para decidir cuando cargar un telefono celular. Es fundamental modelar la soluci´on de un problema mediante un algoritmo antes de comenzar a programar, pues el algoritmo es independiente del lenguaje de programaci´on. Una vez modelado el problema, s´olo debemos adaptarlo al lenguaje en el que deseamos escribir la respuesta para poder realizar lo pedido. Cabe destacar que este documento no tiene por fin ense˜nar algoritmos ya que es un tema perteneciente a otros cursos. Se propone al lector que averigue un poco acerca de ellos para facilitar la modelaci´on de los problemas planteados. Veamos a continuaci´on otros dos ejemplos ilustrativos. Ejemplo 2.2 Dise˜ ne un algoritmo que filtre el ingreso de personas a un casino. Una persona puede entrar a un casino si tiene m´as de 18 a˜ nos y si paga su entrada. 4
Figura 2.2: algoritmo para filtrar el ingreso de personas a un casino. Antes de continuar es necesario conocer el concepto de variable. En computaci´on una variable es un espacio en memoria reservado para almacenar informaci´on que puede o no ser conocida. En general a las variables les daremos un nombre y le asignaremos valores seg´un corresponda. Ejemplo 2.3 Dise˜ ne un algoritmo que dado un n´umero natural n positivo, retorne la suma de los n primeros n´umeros naturales.
Figura 2.3: algoritmo para retornar la suma de los primeros n naturales.
5
Para finalizar la secci´on, cabe destacar que la modelaci´on de los problemas ser´a repasada antes de dar soluci´on a los ejemplos y ejercicios planteados en este texto, con el fin de mostrar la importancia de programar en base a un modelo previo.
2.2.
Creando un nuevo proyecto en Python
A continuaci´ on detallaremos c´omo iniciar un nuevo proyecto en Python 3 usando el IDLE, el entorno de programaci´ on disponible en http://www.python.org/download. Para esto abrimos IDLE. Luego, para crear un nuevo proyecto debemos presionar ctrl+n o ir a la pesta˜na File y abrir una ventana nueva:
Figura 2.4: creando un nuevo proyecto en el IDLE. Se nos abrir´a una nueva ventana en la que debemos escribir el c´odigo de nuestros programas. Luego al guardar alg´ un archivo escrito en esta ventana generaremos un archivo de extensi´on .py. Nuestro primer proyecto en Python ser´a el famoso “Hello world!” 1 , que consiste en un programa que imprime en pantalla “Hello world!”. Para esto escribimos: print ( " H e l l o w o r l d ! " )
Y luego para ejecutarlo presionamos f5 o Run Module en la pesta˜na Run.
1
En general, este programa es el primero que se escribe al aprender un nuevo lenguaje
6
Figura 2.5: primer programa en Python.
7
Cap´ıtulo 3
Tipos de datos, expresiones y control de flujo 3.1.
Tipos de datos
En Python, todo elemento tiene un tipo. Este tipo determina las acciones que podemos realizar sobre el elemento o bien el dominio de los valores posibles que puede tomar. Para declarar y asignarle un valor a una variable en Python debemos usar el simbolo =. Entre los tipos de valores posibles destacan varios. int : una variable de tipo int representa un n´umero entero o en ingl´es “integer ”. Puede tomar valores enteros y es posible realizar operaciones aritm´eticas sobre ´el. Por ejemplo 1 : # R ec or da r a =2 b =5 c = a + b # La d=5/2 # L a e= b %a # La
q ue a l u sa r e l s im bo lo # e s u na l in ea c om en ta da q ue n o i nf lu ye e n e l p ro gr am a
v ar ia bl e c t ie ne el v al or 7 v ar ia bl e d t ie ne e l v al or 2 .5 v ar ia bl e e t ie ne el v al or 1 , q ue es el r es to de 5 /2
float : una variable de tipo float representa un n´umero racional. Su nombre proviene de “ floating point ” (punto flotante en espa˜nol) y es posible realizar operaciones aritm´eticas sobre ´el. El siguiente c´odigo muestra algunos procedimientos b´asicos: a=2.5 b=5.1 c = a + b # L a v ar ia bl e c t ie ne e l v al or 7 .6 d=5/2 # L a v ar ia bl e d t ie ne e l v al or 2 .5 e=5//2 # L a v ar ia bl e e t ie ne e l v al or 2 , c or r es po n di en t e a l a d iv is io n e nt er a e nt re 5 y 2 f=2**4 # La v ar ia bl e f t ie ne el v al or 16 , q ue e s 2 e le va do a 4.
str : los objetos de tipo str son los tipos llamados strings. Los strings sirven para representar texto mediante una “cadena de caracteres”. Es importante notar que la concatenaci´on de dos strings se hace con el operador + y que todo texto entre comillas representar´a strings. Como por ejemplo: 1
El c´ odigo en Python no llevar´ a tilde puesto que se cae en algunos sistemas operativos. La raz´on de esto escapa a los conocimientos del curso.
8
t e xt o 1 = " h o l a " t e xt o 2 = " c h a o " t e xt o 3 = t e xt o 1 + t e xt o 2 # E s ta v a ri a bl e t i en e v a lo r " h o la c ha o "
bool : los objetos de tipo bool son variables que pueden tomar s´olo dos valores True o False. Son de mucha importancia, pues pueden representar condiciones de t´ermino o de fin de un programa o una parte de este. Es u ´ til saber lo siguiente:
•
Para saber si una variable a es igual a otra variable b debo escribir a==b. Esto es v´alido tanto para tipos int , float y str entre otros.
•
Para saber si una variable a es mayor o igual a otra variable b debo escribir a >= b.
•
Para saber si una variable a es menor o igual a otra variable b debo escribir a <= b.
•
Para saber si una variable a es mayor a otra variable b debo escribir a >b.
•
Para saber una variable a es menor a otra variable b debo escribir a
Existen adem´as tres operadores booleanos que debemos conocer: •
and : representa el operador l´ogico ∧.
•
or : representa el operador l´ogico ∨.
•
not : cambia el valor de verdad de una variable booleana.
Ejemplos de variables booleanas ser´ıan los siguientes: v a ri a bl e 1 = 2 > 5 # E st a v a ri a bl e t i en e v a lo r F a ls e v a ri a bl e 2 = 3 < 5 # E st a v a ri a bl e t i en e v a lo r T ru e v a r i a bl e 3 = True # E s ta v a ri a bl e t i en e v a lo r T ru e v a ri a bl e 4 = 5 == 5 # E st a v ar ia bl e t ie ne v al or T ru e y a q u e 5 e s i gu al a 5 t ex t = " h o l a " v ar 5 = t ex t = = " h o l a " # E st a v ar ia bl e e s T ru e v ar 6 = 5 == "5 " # E st a v ar ia bl e e s F al se p ue s e l e nt er o 5 e s d is ti nt o a l s tr in g ( o c ar ac te r ) 5 v ar 7 = 5 >=4 # E st a v ar ia bl e es T ru e p ue s 5 es m ay or o i gu al a 4 d is t = 5 != 4 # E st a v ar ia bl e e s T r ue p ue s 5 e s d is ti nt o d e 4 n o di s t = no t (5!=4) # E st a v ar ia bl e e s F al se p ue s n eg am os e l v al or d e 5 != 4 h ol a = 5 >4 an d 5 <4 # E st a v ar ia bl e e s F al se p ue s a nd e xi ge q ue t od as l as c la us ul as s ea n T ru e c ha o = 5 >4 or 5 <4 # E st a v ar ia bl e e s T ru e p ue s o r e xi ge q ue u na d e l as c la us ul as s ea T ru e
Cabe destacar la existencia del tipo None que es el tipo nulo, es decir, es una variable a´un no inicializada. Tambi´en recordemos que existen varios otros tipos. Se propone al lector buscarlos.
3.2.
Comandos B´ asicos
Python incluye algunos comandos b´asicos que debemos conocer antes de comenzar a programar. Estos son funciones que vienen implementadas en Python. Cabe destacar que el concepto de funci´on es bastante amplio y se detallar´a con profundidad en los siguientes cap´ıtulos del texto. Por ahora, nos bastar´a con saber que una funci´o n es una entidad que recibe ciertos par´ametros, y en base a eso, ejecuta ciertas acciones que pueden terminar con el retorno de un valor. Las funciones m´as b´asicas (y que necesitamos hasta ahora) son las siguientes:
9
print : print es una funci´on que recibe como par´ametro un string y lo imprime en la consola. Tambi´ en recibe par´ ametros que no sean strings y los imprime, como int y float pero es importante saber que si queremos escribir texto y concatenarle una variable que no es string, esta variable debe ser tratada como string mediante str (). Veamos esto en un ejemplo: print print a = 3 print print print
( " h o l a ") # E s t o i m pr i me e n c o ns o la h o la ( " Mi n om br e e s: "+" M i g u e l ") # E st o i mp ri me e n c on so la M i n om br e e s : M ig ue l ( a) # E st o i mp ri me e n c on so la 3 ( " El n um er o e s: "+a ) # E st o g en er a e rr or d e t ip os ( " El n um er o e s: "+ st r (a)) # E st o i mp ri me e n c on so la E l n um er o e s: 3
input : input es una funci´on que recibe como par´ametro un string y pide otro string en consola. Este puede ser asignado a una variable. Si quisieramos pedir n´umeros, debemos transformar el string ingresado en n´umero mediante int () o float (). Se debe realizar lo mismo al recibir un bool (). Ejemplos de esto escritos en Python son: a = input (" Di ga un n om br e : ") b = in t ( input (" Di ga u n n um er o : ")) c = in t ( input (" D ig a o tr o n um er o : " )) print ( " La s um a d e l os n um er os d e " + a +" e s : " + st r (b+c))
Figura 3.1: resultado del ejemplo de intput .
3.2.1.
Operadores
Para los tipos float e int existen operadores entre dos n´umeros a y b: +: entrega la suma de los n´umeros a y b. −: ∗:
entrega la resta de los n´umeros a y b. entrega la multiplicaci´on los n´ umeros a y b.
/: entrega la divisi´on de los n´ umeros a y b. //: entrega la divisi´on entera de los n´umeros a y b. 10
%: entrega el resto de la divisi´on de los dos n´ umeros a y b. ∗∗:
3.3.
entrega el resultado de elevar a por b.
Programas b´ asicos
Con los conocimientos adquiridos hasta el momento ya es posible hacer programas b´asicos que interact´ uen con el usuario pedir un input y devolver algo en consola. Los dos ejemplos presentados a continuaci´on ilustran de buena forma lo que somos capaces de hacer: Ejemplo 3.1 Escriba un programa que pida al usuario el lado de un cuadrado y entregue el ´area, el per´ımetro y el valor de su diagonal. En este problema debemos hacernos cargo de tres cosas: Recibir el valor del input y guardarlo como un float . Hacer las operaciones aritm´eticas respectivas. Imprimir en pantalla los resultados pedidos. Notamos que el primer requerimiento lo hacemos con la funci´on input . El segundo requerimiento se logra al hacer las operaciones aritm´eticas pertinentes y almacenarlas en variables. El tercer requerimiento hace uso de la funci´on print . La soluci´ on propuesta es: l ad o = float ( input ( " I n gr e se e l l ad o d el c u ad r ad o : " )) p e ri m et r o = l a do * 4 a re a = l a do * * 2 d i a g o na l = l a do * ( 2 * * ( 1 / 2 ) ) print (" El p er im et ro e s: "+ st r ( p e ri m et r o ) ) print (" El a re a es : "+ st r ( a re a )) print (" La d ia go na l e s : " + st r ( d i ag o na l ) )
Ejemplo 3.2 Usted est´a en un curso en el que tiene 3 pruebas que ponderan un 20 % cada una, y un examen quepondera el 40 % restante. El curso se aprueba si el promedio no aproximado del curso es mayor o igual que 4.0. Escriba un programa que reciba las 4 notas e imprima True si usted aprueba el curso y False en caso contrario. Para resolver el ejemplo debemos recibir las notas correspondientes y realizar las operaciones aritm´eticas pertinentes. Aquel valor se compara a 4.0 para ser asignada la respuesta a una variable booleana. Luego esta se imprime en consola. n1 = float ( input ( " I ng re se n2 = float ( input ( " I ng re se n3 = float ( input ( " I ng re se ex = float ( input ( " I ng re se p as as te = ( 0. 2* n 1 + 0. 2* n 2 print ( p a s a s t e )
l a n ot a d e l a p ru eb a 1 : " )) l a n ot a d e l a p ru eb a 2 : " )) l a n ot a d e l a p ru eb a 3 : " )) l a n ot a d el e xa me n : ")) + 0. 2* n 3 + 0. 4* e x ) > =4 .0
Notemos que el programa anterior es equivalente a escribir el siguiente c´odigo: n1 = float ( input ( " I ng re se l a n ot a d e l a p ru eb a 1 : " )) n2 = float ( input ( " I ng re se l a n ot a d e l a p ru eb a 2 : " )) n3 = float ( input ( " I ng re se l a n ot a d e l a p ru eb a 3 : " ))
11
ex = float ( input ( " I ng re se l a n ot a d el e xa me n : ")) print ( ( 0. 2* n 1 + 0 .2 * n2 + 0 .2 * n3 + 0 .4 * ex ) >= 4 .0 )
3.4.
If, elif y else
En el ejemplo 3.2, se obten´ıa como resultado una impresi´on en pantalla de una variable booleana, la que pod´ıa ser True o False . En general, no se desea recibir una impresi´ on en pantalla de la variable booleana, sino que se desea un mensaje distinto dependiendo del valor de la variable. En los lenguajes de programaci´on por lo general existe una manera de ejecutar cierto grupo de acciones dependiendo si una sentencia se cumple o no, es decir, si una variable booleana asociada a la sentencia es verdadera o falsa. En particular, en Python la sintaxis es la siguiente: if < v a r i a b l e y / o e x p r e si o n b o o le a na > : # E j e cu t ar a q ui l as a c ci o ne s i n de n ta n d ol a s
Lo que hace el c´odigo de arriba es ejecutar las acciones declaradas en el if si se cumple la condici´on o si la variable booleana es True . Notemos que tras la variable y/o expresi´on booleana hay dos puntos (:) y que las acciones a ejecutar deben estar indentadas, es decir, desplazada 4 espacios dentro respecto al if declarado (tambi´en se puede hacer click en tab). El ejemplo 3.2 puede ser replanteado de la siguiente manera: n1 = float ( input ( " I ng re se l a n ot a d e l a p ru eb a 1 : " )) n2 = float ( input ( " I ng re se l a n ot a d e l a p ru eb a 2 : " )) n3 = float ( input ( " I ng re se l a n ot a d e l a p ru eb a 3 : " )) ex = float ( input ( " I ng re se l a n ot a d el e xa me n : ")) p ro m = 0 .2 * n1 + 0 .2 * n2 + 0 .2 * n3 + 0 .4 * ex if p r om > = 4. 0 : print ( " F e l i c i ta c i o ne s , a p r o b as t e e l c u r so ! ") # E s to i m pr i me " F e l ic i ta c io n es , a p ro b as t e e l c u rs o ! " s i l a v a ri a bl e p r om e s m a yo r o i g ua l a 4 .0
Cabe destacar que se considera “dentro de un if” todo lo que est´e indentado. Puede haber un if dentro de otro if , y las instrucciones de este deben estar indentadas seg´un corresponda. Ejemplo 2.3 Cree un programa que dado un n´umero, determine si es par e imprimir en consola si lo es. Adem´as si es par, el´evelo al cuadrado. Al t´ermino del programa, desp´ıdase con un. “Adios mundo!” independiente de si el n´umero era par o impar. Es importante saber que en esta oportunidad, si se cumple la condici´on de ser par se deben ejecutar dos instrucciones: Imprimir en consola que es par. Elevarlo al cuadrado. Luego de esto, hay que escribir un “Adios mundo!” fuera del if , ya que esto debe ser independiente de la condici´on de paridad. a = in t ( input ( " I ng re se e l n um : " )) v ar = a %2 == 0 if var: # Es p o si b le p o ne r u na v a ri a bl e t i po b o ol print ( " E s p ar " ) print (a**2) # E st as l in ea s s e e je cu ta n s ol o s i a e s p a r print (" A d i o s m u n d o ! " ) # N o te m os q ue n o e st a i n de n ta d o # I nd e pe nd ie nt e d e l a p ar id ad d e a s e e je cu ta ra l a l in ea
Ahora bien, nos interesar´a tambi´en ejecutar acciones cuando no se cumpla la condici´on pero si se cumpla otra. Para esto existe la entidad elif, la que viene despu´es de un if. Si la condici´on del if no se cumple, pero si se cumple 12
la condici´ on del elif, se ejecutar´a el grupo de instrucciones que est´a indentadas en el elif. Despu´ es de la condici´ on deben ir los dos puntos (:) y adem´as el elif no debe estar indentado respecto al if original. Es posible adem´as no poner uno, sino que varios elif. Tambi´ en nos interesa tener la entidad else, que viene despu´ es de un if o elif. Se ejecuta si ninguna de las condiciones anteriores fue ejecutada y no recibe una condici´on (variable tipo bool ) pero si debe ir acompa˜nada de dos puntos (:). Debemos tener en cuenta que: Un if puede ir sin acompa˜narse de un elif o un else . Un else o un elif debe estar precedido por un if o un elif . Es posible anillar estas entidades, unas dentro de otras. Ejemplo 3.4 Dise˜ nee un programa simple que decida cargar el celular si le queda poca bater´ıa. # Es l le va r a P yt ho n l a i de a d el e je mp lo 2 .1 b at = input ( " B a t e r i a b a j a ? \ n 1 ) S i \ n 2 ) N o \ n ") # \n e s u n s al to d e l in ea if b at = = 1 : print (" C a r g a r c e l u l a r " ) else : print (" No c ar ga r " )
Ejemplo 3.5 Dise˜ ne un programa que reciba dos n´umeros a y b y una operaci´on aritm´etica (representada por un n´umero) entre las cuatro b´asicas. Si la operaci´on no es correcta decir que no fue posible realizarla. Imprimir en consola los resultados. a = float ( input ( " I n gr e se e l p r im e r n u me r o : " )) b = float ( input ( " I n gr e se e l s e gu n do n u me r o : " )) op = input ( " I ng re se l a o pe ra ci on : \ n 1) S um a \ n2 ) R es ta \ n3 ) M ul t \ n4 ) D iv \ n") if o p = = "1 " : s = a+ b print (" La s um a es : "+ st r (s)) elif o p = = " 2" : r = a -b print (" La r es ta e s: "+ st r (r)) elif o p = = " 3" : m = a* b print (" L a m u lt i p li c a ci o n e s : " + st r (m)) elif o p = = " 4" : d = a/ b print (" La d iv is io n e s: "+ st r (d)) else : print ( " N o f ue p o si b le r e al i za r o p er a ci o n ") print ( st r (a)+ " ? "+ st r (b)) print ( " A d i o s ! ")
Antiejemplo 3.1 Pedir 3 n´ umeros que representan cada uno lados de un tri´angulo. Ver si el tri´ angulo es equil´atero, is´osceles o escaleno. Un error muy frecuente es escribir el siguiente c´odigo: a = float ( input (" I ng re se e l p ri me r l ad o : " )) b = float ( input (" I n g re s e e l s e gu n do l a do : " ))
13
Figura 3.2: ejemplo 3.5, la calculadora. c = float ( input (" I ng re se e l t er ce r l ad o : " )) if a==b an d b = = c : print (" E q u i l a t e r o ") if a==b or b = = c or a = = c : print (" I s o s c e l e s ") else : print ( " E s c a l e n o ")
Lamentablemente este programa no es correcto, ya que si nuestro input es el de un tri´angulo equil´ atero, como por ejemplo a =1, b =1 y c =1, el programa imprime en pantalla equil´atero e is´osceles, lo que no es correcto. Esto sucede porque si se cumple la primera condici´on, no se excluye de la ejecuci´on al segundo if , ya que eso lo har´ıa un elif (recordemos que el elif se ejecuta solamente si no se cumpli´o la condici´on anterior, en cambio un if lo har´ıa siempre). Una soluci´ on correcta ser´ıa: a = float ( input (" I ng re se e l p ri me r l ad o : " )) b = float ( input (" I n g re s e e l s e gu n do l a do : " )) c = float ( input (" I ng re se e l t er ce r l ad o : " )) if a==b an d b = = c : print (" E q u i l a t e r o ") elif a = = b or b = = c or a = = c : # En v ez d e i f p us im os e li f print (" I s o s c e l e s ") else : print ( " E s c a l e n o ")
14
Ejemplo 3.6 Pida al usuario 3 n´ umeros que representan los coeficientes de una ecuaci´on cuadr´atica a, b, c. Imprima en pantalla: Que no es cuadr´atica si a = 0 Que tiene dos soluciones reales si b 2 − 4ac ≥ 0. Que tiene una soluci´on real si b 2 − 4ac = 0. Que no tiene soluciones reales si b 2 − 4ac ≤ 0. Al realizar este problema debemos comprobar si es o no es cuadr´atica. En el caso de que lo sea, debemos hacer un an´alisis de sus posibles soluciones: a = float ( input ( " I ng re se e l a d e l a e cu ac io n : " )) b = float ( input ( " I ng re se e l b d e l a e cu ac io n : " )) c = float ( input ( " I ng re se e l c d e l a e cu ac io n : " )) if a ! =0 : if b ** 2 - 4 *a *c >= 0: print ( " T i en e d os s o lu c io n es r e al e s ") elif b **2 - 4* a* c = = 0: print ( " T i en e u na s o lu c io n r e al ") elif b **2 - 4* a* c <= 0: print ( " T i e n e s o l u c i o n e s c o m p le j a s ") else : print ( " N o e s c u ad r at i ca " )
3.5.
Loops
Al momento de resolver un problema, nos intereser´a ejecutar acciones mientras se cumpla una condici´on. En Python podemos realizar esto con la entidad while y for , las que ejecutar´an las instrucciones que tengan indentadas una y otra vez mientras se sigan cumpliendo determinadas condiciones.
3.5.1.
While
La entidad while repite las instrucciones indentadas mientras una expresi´on booleana sea True . Es posible poner tambi´en una variable de tipo bool dentro. while < C o n d i c i o n y / o v a r i ab l e b o ol e a na > : # I n s t r u c c i on e s i n d e n ta d a s q u e s e r a n e j e c u ta d a s
Es importante notar que podemos poner un while dentro de otro while respetando la indentaci´on, y tambi´en es posible poner las entidades condicionales if , elif , else . Al momento de usar un while en un programa se debe ser cuidadoso, puesto que si la expresi´on booleana nunca llega a ser falsa el programa puede quedar en un loop infinito y no terminar. Ejemplo 3.7 Hacer un programa que imprima los n´umeros del 1 al 10 en consola. Para realizar este programa, debemos tener un variable (que llamaremos contador) que diga el n´umero de iteraci´on en la que est´a el loop y se imprima en pantalla seg´un corresponda. Cuando el contador supere el 10, saldr´a del loop.
15
c ou nt = 1 while c o un t < = 1 0 : print ( c o u n t ) c ou nt = c ou nt + 1 # c o un t a u me n ta e n c ad a i t er a ci o n # C ua nd o c ou nt s ea 1 1, n o v ol ve ra a e nt ra r e n e l l oo p y s e t er mi na e l p ro gr am a
Obs: otra opci´on v´alida para hacer esto es lo siguiente: c ou nt = 1 s e gu i r = True while seguir: print ( c o u n t ) c ou nt = c ou nt + 1 if c ou n t = = 1 1: s e gu i r = False
Ejemplo 3.8 Pedir al usuario un natural n e imprimir en pantalla el factorial de dicho n´umero. Para realizar este programa, adem´as de llevar un contador de iteraci´on, debemos tener una variable que lleve el valor del factorial: n = in t ( input ( " I ng re se e l n um er o n : " )) c ou nt = 1 mu lt = 1 while c o un t < = n : mu lt = mul t * co un t c ou nt = c ou nt + 1 print ( m u l t )
3.5.2.
For
Un for es una entidad que recorre de manera determinada los elementos de una lista y ejecuta las instrucciones que tenga indentadas. Si bien el cap´ıtulo de listas es p osterior, y en ´ el aprenderemos a usar bien la entidad for, es posible entender lo b´asico para usar for como un loop. Posee la siguiente sintaxis: fo r < v a r i a b l e l o ca l > i n < l i st a > : # G r up o d e i n s tr u cc i o ne s a e j ec u ta r # P ue de n u sa r o n o a l a v ar ia bl e l oc al
Es necesario antes conocer antes la funci´on range . range representa una secuencia de n´umeros y es usada frecuentemente para inicar loops en donde se conoce el n´umero de iteraciones mediante un for 2 . Se inicializa de la siguiente manera: a = range (
,) b = range (,,< intervalo >)
Donde n´ umero inicial es el n´ımero en que parte la secuencia, n´umero final es el sucesor del ´ultimo n´ umero de la secuencia, y si se inicializa con intervalo, el intervalo entre n´umero y n´umero es ese (Si no est´a inicializado con intervalo, avanza de 1 en 1). Por ejemplo: 2
Esta definici´ on fue extra´ıda de la documentaci´ on oficial de Python
16
range (1,10) tiene los n´umeros 1, 2, 3, 4, 5, 6, 7, 8, 9. range (1,10,2) tiene los n´umeros 1, 3, 5, 7, 9. range (1,10,3) tiene los n´umeros 1, 4, 7. As´ı, el siguiente for : fo r i in range ( 1 , 10 ): # A c c i o n es i n d e n ta d a s
hace nueve iteraciones, una para cada valor que toma i. Empezar´a en 1, luego valdr´a 2, e incrementar´a hasta llegar a 9. Ejemplo 3.9.1 Imprimir en pantalla los n´umeros pares entre 1 y 10 excluy´ endolos. fo r i in range ( 2 , 10 , 2) : print (i )
Ejemplo 3.9.2 Imprimir en pantalla los n´umeros impares entre 1 y 10 sin excluirlos. a= range ( 1 , 10 ,2 ) fo r i i n a : # N o te mo s q ue i n ic ia li z am os e l r an ge a nt es d e u sa rl o e n e l f or print (i )
Ejemplo 3.10 Pedir un n´ umero natural n e imprimir en pantalla los numeros primos entre 1 y n. Recordemos que un n´umero es primo si solamente es divisible por 1 y por si mismo. Para determinar si un n´umero n es primo podemos dividirlo desde 2 hasta n − 1. Podemos llevar una variable booleana (ser´a True si el n´umero es primo) que por defecto sea True y que cuando el resto de la divisi´on entre n y alg´ un n´ umero i entre 2 y n − 1 sea 0 (i.e. n es divisible en i) se haga False . Podemos llevar un loop que seleccione de 1 en 1 el n´umero n a comprobar si es primo, y dentro de este loop, otro que vaya dividiendo por todos los x entre 2 y n − 1. Cuando salga del loop interior, si la variable booleana sigue siendo verdadera, imprimir´a el n´ umero. Luego debe continuar con el loop extrerior para comprobar todos los n´umeros restantes, luego de reseteada la variable bool a True . n = in t ( input ( " I ng re se e l n um er o n : " )) e s Pr i mo = True fo r i in range ( 2 , n + 1 ): fo r x in range (2,i): if i %x = =0 : e s Pr i mo = False # N o ta r q ue l a l i ne a a c o n ti n ua c io n e st a a f ue r a d el l oo p i n te r no , p er o d e nt r o d el e x te r io r if e s P ri m o : print ( i) e s Pr i mo = True # D e be m os r e se t ea r l a e s Pr i mo a n te s d e v o lv e r a l l oo p e x te r io r
3.5.3.
Break y continue
A veces no deseamos declarar variablas tipo bool adicionales para continuar o parar con un loop. Para esto existen dos entidades llamadas break y continue . Al ejecutar un break dentro del loop, este terminar´a, y no ejecuta ninguna de las instrucciones dentro del loop que estaban debajo del break. En cambio continue hace que el loop pase a la siguiente iteraci´on saltandose todas las lineas dentro del loop que estuviesen despu´es del continue .
17
Ejemplo 3.11 Escriba el programa que imprime los primeros 10 naturales en pantalla usando break y continue . c ou nt = 1 w h i le T r ue : print ( c o u n t ) c ou nt + = 1 # E st o e s l o m is mo q ue e sc ri bi r c ou nt = c ou nt + 1 if c o u nt < = 10 : continue else : break
Notemos que con buen manejo de variables de tipo bool es posible realizar lo mismo que haria un break o un continue . Queda a criterio del programador la v´ıaa que utilizar´a cuando necesite usar loops para resolver un problema. Ejemplo 3.12 Dise˜ ne un programa que reciba dos n´umeros a y b y una operaci´on aritm´ etica entre las cuatro b´asicas representada como un n´umero. Si la operaci´on no es correcta decir que no fue posible realizarla. Imprimir en consola los resultados. Luego de esto, preguntarle al usuario si desea realizar otra operaci´on. Si responde “si”, ejecutar nuevamente el programa. Nuevamente es un ejemplo conocido, pero esta vez debemos a˜nadir un loop que nos mantenga en el programa hasta que deseemos salir. Hay varias formas de hacer esto, pero la propuesta es la siguiente: s= " s i " w h i le T r ue : if s != " s i ": break a = float ( input ( " I ng re se e l p ri me r n um er o a : " )) b = float ( input ( " I ng re se e l s eg un do n um er o b : " )) op = input ( " I n gr e se l a o p er a ci o n : \ n 1 ) S u ma \ n 2 ) R e st a \ n 3 ) M u l \ n 4 ) D i v \ n ") if o p = = " 1" : s = a+b print ( " La s um a e s: "+ st r (s)) elif o p = = " 2 ": r = a -b print ( " La r es ta e s: "+ st r (r)) elif o p = = " 3 ": m = a* b print ( " La m ul t e s: "+ st r (m)) elif o p = = " 4 ": d = a/b print ( " La d iv es : " + st r (d)) else : print ( " I n g r e se o p e r a ci o n v a l i da " ) s = input ( " D e s e a s e g u i r ? " )
18
Cap´ıtulo 4
Funciones y m´ odulos 4.1.
Funciones
Ya hab´ıamos hablado anteriormente de funciones como entidades que reciben par´ametros y realizan un conjunto de acciones. Sin embargo debemos ahondar un poco m´as. Una funci´on es una secci´on apartada del codigo que ejecuta ciertas acciones en base a par´ametros entregados. Luego puede retornar un valor o no retornar nada. Una funci´on por si sola no hace nada, y la idea es utilizarla en el programa al llamarla. Una ventaja muy importante que tienen las funciones es que si queremos reutilizar el c´odigo de una parte del programa, cambiando s´olo ciertos par´ametros, es posible crear una funci´on, y la llamamos las veces que necesitemos cambiando los par´ametros de entrada. La sintaxis es como se sigue: de f < n o m br e f un c io n > ( p a r am e tr o 1 , p a ra m et r o2 , . .. , p a ra m et r oN ) : # A q ui e l c o di g o i n de n ta d o #... return < v a l or d e s a li d a > # P ue de o n o t en er r et ur n
Luego basta con llamar a la funci´on con su nombre en el c´odigo. Cabe destacar que para usar una funci´on debe ser declarada antes del c´odigo en el que se va a utilizar, aunque si otra funci´on usa una funci´on, esto no necesariamente se debe cumplir. Repitamos un ejemplo hecho anteriormente, pero ahora aplicando funciones. Ejemplo 4.1 Pedir un n´umero natural n e imprimir en pantalla los n´umeros primos entre 1 y n. Se repite el concepto hecho en el cap´ıtulo anterior, p ero esta vez para determinar si un n´umero es primo se aplicar´a una funci´on: de f e s P r im o ( n u m ) : # n um e s e l p ar am et ro d e e nt ra da q ue r ep re se nt a e l n um er o q ue q ue re mo s s ab er s i e s p ri mo # Es u na v ar ia bl e l oc al y n o i nf lu ye f ue ra d e l a f un ci on p r im o = True fo r i in range ( 2 , n um ) : if n um %i = =0 : p r im o = False return primo # R e to rn a T ru e s i u n n um er o n um e s p ri mo n = in t ( input ( " I n gr e se u n n u me r o : " )) fo r i in range (2,n): if esPrimo(i): # L la ma mo s a l a f un ci on e n c ad a i te ra ci on print (i )
19
Ejemplo 4.2 Cree dos funciones que dado el lado de un cuadrado, una retorne su per´ımetro, otra su ´area, y otra el valor de su diagonal. de f p e r i m e tr o ( l a d o ) : return 4*lado de f a r ea ( l a d o ) : return lado**2 de f d i a g on a l ( l a d o ) : return l a d o * ( 2 * * 0. 5 ) # A h or a l as u s ar e mo s e n u n p r og r am a l = float ( input ( " I ng re se e l l ad o : " )) a = p er im et ro ( l ) b = a rea ( l) print (a ) print (b ) print ( d i a g o na l ( l ) ) # A qu i n o a s ig n am o s d i ag o na l ( l ) a u na v a ri a bl e
Cabe destacar que una funci´on retorna un valor si y s´olo si tiene return. Si esta finaliza con un print y no posee return, esta funci´on no se puede asignar a una variable: de f unaFunc(s): print ( s+ " a l gu n s t ri n g ") de f otraFunc(s): a = s+ " a l gu n s t ri n g " return a # v a lo r = u n aF u nc ( " h o la " ) E st o t ir a e r ro r ! ! v a lo r = o t ra F un c (" h o l a ") E st o e s p os ib le
Es necesario recalcar que adem´as al llegar al return no se sigue ejecutando ning´un otro c´odigo dentro de la funci´on aunque este exista c´odigo m´as abajo.
4.2.
M´ odulos
Un m´odulo en Python es una colecci´on de funciones y constantes que pueden ser importadas desde cualquier otro programa. En general, cuando creamos un programa, y lo guardamos con extensi´on .py , estamos creando un m´odulo. Python trae varios implementados. Entre los m´as destacados est´an random y math. Para usar un m´odulo implementado por Python se debe escribir lo siguiente: f r o m < N o m b re de l modulo > import < N o m br e d e l o q ue d e se a mo s i mp o rt a r >
Obs. Tambi´en es posible: import # L u eg o p a ra u s ar l a f u nc i on u s am o s < N o mb r e d el m od ul o > . < N om b re d e l a f un ci o n >
Si el m´odulo que queremos usar es uno de los que guardamos nosotros se debe hacer de la misma manera, pero el programa en el que convocamos al m´odulo debe estar guardado en la misma carpeta que el m´odulo que estamos importando. Podemos importar de ´el las funciones definidas. Luego podemos usar la entidad importada. Queda a criterio del lector buscar los m´odulos que necesite y averiguar las funciones pertinentes. Veamos un ejemplo:
20
Ejemplo 4.3 Usando el m´odulo math, dado cierto radio, calcular el ´area y el per´ımetro de un c´ırculo. Se realizar´a con funciones. Usaremos la constante Pi implementada en el m´odulo math : f r o m m a t h import pi de f perimetroCirc(radio): return 2*pi*radio de f areaCirc(radio): return pi*(radio**2) r = float ( input ( " I n gr e se e l r a di o : " )) print ( p e r i m e t r o C i r c ( r ) ) print ( a r e a C i r c ( r ) )
En s´ıntesis, cuando tenemos un programa de Python guardado en un.py, podemos usar funciones que est´en en otros archivos .py si importo la funci´on. Esto es an´alogo a dividir nuestro programa en varias hojas, y cuando importo funciones, las pego en la hoja que las est´a, logrando as´ı un programa m´as grande. Adem´as en general, cuando tengamos proyectos grandes, es aconsejable dividirlo en varios m´odulos, para que su posterior edici´on sea m´ as sencilla.
4.3.
Main
Cuando nosotros tenemos un m´odulo que aparte de funciones tiene c´odigo que se ejecuta como en el ejemplo 4.3, si llegamos a importar ese m´odulo, aunque no lo queramos, en nuestro programa se ejecutar´a el c´odigo que no fue declarado dentro de una funci´on. Supongamos que tenemos un m´odulo con el c´odigo del ejemplo 4.3 llamado Circ, y adem´as tenemos otro programa en que importamos la funci´on perimetroCirc. El resultado ser´ıa el siguiente: Antes de ejecutar el codigo de nuestro programa (un simple “hello world”) se ejecuta el c´odigo del m´odulo, en que ped´ıa un radio e imprim´ıa en consola el per´ımetro y el ´area del c´ırculo asociado. Para esto, debemos agregar un condicional en el m´odulo Circ que incluye todo el c´odigo “ejecutable” (es decir, el c´odigo no definido como funci´on). En general, cuando tengamos un m´odulo, y queramos mantener c´odigo ejecutable, pero queremos que se ejecute s´ olo si lo estamos abriendo desde el mismo m´odulo, este debe ir indentado en el siguiente if: if _ _ n a me _ _ = = " m a i n " : # C o d i g o e j e c u ta b l e
As´ı, el m´odulo Circ quedar´ıa: f r o m m a t h import pi de f perimetroCirc(radio): return 2*pi*radio de f areaCirc(radio): return pi*(radio**2) if _ _ n a me _ _ = = " m a i n " : r = float ( input ( " I ng re se e l r ad io : " )) print ( p e r i m e t r o C i r c ( r ) ) print ( a r e a C i r c ( r ) )
Y si importamos en alg´on otro programa el m´odulo Circ.py, no se ejecutar´a aquel c´odigo (el programa de la figura 3.1 imprimir´ıa sencillamente un “hello world”).
21
Figura 4.1: problemas con m´odulos. Obs. Es una buena pr´actica de programaci´on no escribir c´odigo ejecutable en un m´odulo si s´olo queremos definir en ´el funciones. Si deseamos hacer un programa relativamente grande, el ejecutable debe ir en un m´odulo separado que importe todos los dem´as m´odulos en los que est´an declaradas las funciones por usar.
22
Cap´ıtulo 5
Strings 5.1. 5.1.
Decl Declar arac aci´ i´ o n y manejo de strings on
Hasta ahora hemos aplicado conceptos sobre todo aritm´ eticos eticos y matem´aticos aticos simples. Pero ¿Qu´e hay acerca del procesamiento de texto en Python?. Ya hemos introducido un tipo llamado string que correspone a la representaci´ on on de una cadena de caracteres. Este cap´ cap´ıtulo busca ilustrar parte de las funciones m´as as importante a la hora de trabajar con strings. strings. Una variable se declara de tipo string cuando se le asigna texto entre “ ” o bien se le asigna el retorno de una funci´ on de tipo string. Por ejemplo: on s = " Ho Ho la la , s oy o y u n s t ri ri n g " # D e c la la r ac a c i on o n d e u n s t ri ri n g s2 = input ( " I n gr g r e se se s u t e xt xt o ") " ) # R e c or or d em e m o s q ue ue i np n p u t g u ar ar d a c om om o # s t ri r i n g e l t e xt xt o i n gr g r e sa s a d o p or o r e l u s ua ua r io io .
Para el manejo de string es posible usar utilidades que ya vienen implementadas en python: Para saber la cantidad de caracteres de un string usamos la funci´on len: s = "mensaje" a = le n ( s ) # Es E s t a v a ri ri a bl b l e t i en en e e l v a lo lo r 7
Para acceder al i-´ esimo esimo caracter de un string es posible p osible hacer lo siguiente: s = " Ho H o la la , s oy o y u n s t ri ri n g " a = s [ 0 ] # E st st a v a ri r i a bl b l e t i en en e e l v a lo lo r " H " b = s [ 1 ] # E st st a v a r ri i a bl b l e t i en en e e l v a lo lo r " o "
Notemos que el carater en la primera posici´on o n es el 0 y que la ´ultima ultima posici´ on on es la len(s) −1. Para saber si un caracter o un string forma parte de un string: s = " Ho H o la la , s oy o y u n s t ri ri n g " v ar ar = " a " in s # V a ri ri a bl bl e b o ol ol e an a n a q ue u e t o ma ma e l v al a l o r T ru ru e # P ue u e s e l c ar a r ac a c te t e r a e st st a e n e l s tr t r in in g .
23
v ar a r 2 = " H o l a " in s # V ar a r i ab a b l e b o ol o l e an an a q ue u e t om o m a e l v a lo lo r T ru ru e v ar a r 3 = " C h a o " in s # V a ri r i a bl b l e b o ol o l e an an a d e v a lo lo r F a ls ls e
Para saber el orden seg´ un la tabla ascii de dos strings podemos usar < o >. un > . Un string es “mayor que otro” si un un la tabla ASCII1 es posterior. el orden orde n alfa a lfab´ b´etico etic o seg´ p osterior. Notar que si se desea el orden alfab´ etico etico se desea hacer normalmente se debe hacer convirtiendo todo a min´uscula uscula o may´uscula. uscula. s = "Alameda" s2 = " P r o v i d e n c i a " a = ss2 # a t om o m a e l v al al or o r T ru ru e # b t om o m a e l v al al or o r F al a l se se
variable ser´ ser´a True si True si s1 est´a alfab´eticamente eticamente antes que s2 de s2 de lo contrario ser´a False Para Para extraer extraer parte de un string y almacenarl almacenarloo (en otros lenguajes esto se hace con una funci´ funci´on llamada subsllamada substring) tring) debemos hacer string [x:y] [x:y] que toma el string desde la posici´on on x hasta la y-1. Por ejemplo: s = " S oy oy u n s t ri ri n g " a = s [ 0: 0 : 5] 5] # a t ie i e ne ne e l v a al l or o r " S oy oy u " b = s [ 3: 3 : 7] 7] # b t i en e n e e l v al al or or " u n " c = s [: [ : 7] 7] # c t ie ie ne ne e l v al al or or " So So y un " d = s [5 [ 5 :] :] # d t ie i e ne n e e l v al a l or o r " n s tr t r in in g " e = s [ 1: 1: - 2] 2] # e t ie i e ne n e e l v al a l or o r " oy o y u n s tr tr i "
Notamos que c, d son esp eciales. Las dos primeras porque carecen de un t´ermino. ermino. Python asume que el usuario intent´o decir que el termino faltante era 0 y len(s) respectivamente. En cuanto a e, que tiene un n´umero negativo, esto se toma como la posici´on on desde derecha derecha a izquierda. izquierda.
5.2. 5.2.
Funci uncione oness de strin strings gs
Existen en Python ciertas funciones que nos permiten realizar varias funciones con los datos de tipo string. Estas funciones requieren una instancia de un string para ser usadas de la forma: string.funcion(parametros)
Algunas de las funciones se presentan a continuaci´on. Se propone al lector que averigue en la documentaci´on on oficial de Python acerca de otras que logre necesitar: 1
Esta tabla se explica en secciones posteriores.
24
replace(stri replace(string1,st ng1,string2) ring2):: Reemplaza Reemplaza en un string el valor valor string1 si est´ a contenido por el valor de string2. s = " h ol ol a h ol o l a c ha h a o h ol ol a " s . r e p l a c e (" ( " c h a o ", " , " h o l a ") ") # A ho h o ra r a e l v al a l or o r d e s e s " h o la la h ol o l a h ol o l a h ol ol a "
isalpha(): isalpha(): Funci´on on que retorna True si el string contiene s´olo olo caracteres caractere s alfab´eticos: eticos: s = " h ol ol a " a = s . i s al al p ha ha ( ) # a p os o s ee e e e l v al a l or o r T ru ru e s="123" a = s . i s al al p ha ha ( ) # a p os o s ee e e e l v al a l or o r F al a l se se
count(string1): count(string1): Funci´on on que retorna un int que cuenta cuantas veces string1 aparece dentro del string. s a b c # # #
= = = = a b c
" h ol ol a h ol o l a c ha h a o h ol ol a " s . co c o un u n t (" (" a " ) s . co c o un u n t (" ( " h o l a ") ") s . co c o un u n t (" ( " c h a o ") ") es 4 es 4 es 0
find(string1): find(string1): Encuentra la primera aparici´on on en el string de string1. Si no existe retorna -1. s = "hola" a = s . fi f i nd n d (" (" a") s2 = " b a b a r o a " b = s 2. 2 . f in in d (" (" b " ) c = s 2. 2 . f in in d (" ( " r o ") ") # a es 3 # b es 0 # c es 4
upper(): upper(): Retorna un string con todos to dos los caracteres alfab´eticos eticos en may´uscula. uscula. s = "hola" a = s . up u p pe p e r () () # a e s " HO H O LA LA "
lower(): lower(): Retorna un string con todos los caracteres alfab´ eticos eticos en min´uscula. uscula. s = "Hola" a = s . lo l o we w e r () () # a e s " ho h o la la "
strip(): strip(): Elimina los espacios de los lados.
25
s = " H ol a t en go e sp ac io s " a = s . st ri p () # a e s " H o la t en go e sp ac io s " # Si , e s m en ti ra , p or qu e a n o t ie ne e sp ac io s a l os l ad os : (
5.3.
El tipo chr y la tabla ASCII
En Python no existe el tipo chr por si solo, sin embargo es posible trabajar con strings de largo 1, es decir, podemos representar caracteres. Un caracter es la representaci´on de 8-bits2 asociado a una tabla llamada ASCII. Esta tabla para cada n´ umero entre 0 y el 255 posee una representaci´on en forma de caracter. En Python para obtener el n´umero asociado a un caracter usamos la funci´on ord(char). En cambio, para obtener el caracter asociado a n´umero usamos la funci´on chr(int). Por ejemplo:
Figura 5.1: ejemplo de ord() y chr(). Es necesario notar que en la tabla ASCII: Las letras en may´uscula de la A a la Z est´an entre los n´ umeros 65 y 90. Las letras en min´uscula de la a a la z est´an entre los n´ umeros 97 y 122. Ejemplo 5.1 Reciba un string por parte del usuario y compruebe si este posee s´olo caracteres alfab´eticos. Luego, si se cumple lo anterior, preguntele al usuario si desea pasar todo el texto a may´uscula o min´ uscula. Para realizar el ejercicio utilizaremos las funciones que detallamos anteriormente: s = input ( " I ng re se s u t ex to : ") if s.isalpha(): s2 = input ( " Q u e d e s e a h a c er ? \ n 1 ) M a y u s cu l a s \ n 2 ) M i n u s c u l a s \ n ") if s 2 = = "1 " : s = s . up pe r () print ( s ) elif s 2 = = " 2" : 2
8 bits es un n´umero de 8 d´ıgitos en binario, que forma la unidad byte
26
s = s . lo we r () print ( s )
Es necesario notar que debemos asignarle a s el valor de la manera s = s.lower() o bien s = s.upper() ya que estas funciones no cambian el valor de s sino que retornan un nuevo elemento con el valor correspondiente a cambiar todas a may´usculas o min´ usculas. Para profundizar en el manejo de strings es necesario pasar al siguiente cap´ıtulo correspondiente a listas.
27
Cap´ıtulo 6
Listas 6.1.
Listas Unidimensionales
Las listas corresponden a un tipo de estructura de datos que son capaces de almacenar variables instanciadas. Informalmente, podemos ver a los arreglos como casilleros en los que guardamos valores, y cada vez que agregamos un valor a la lista se agrega un casillero con una informaci´on correspondiente dentro. Su declaraci´on m´as b´asica es de la forma: miLis ta = []
En donde miLista corresponde a una lista unidimensional capaz de almacenar datos. Su funci´on fundamental es append(valor), que adhiere al final de la lista a valor . Por ejemplo: miLis ta = [] miLis ta . appe nd (1 ) miLis ta . appe nd (2 ) miLis ta . appe nd (3 ) miLis ta . appe nd (4 ) miLis ta . appe nd (5 )
Agregamos a una lista vac´ıa los n´ umeros enteros 1, 2, 3, 4, 5. Si ahora imprimimos la lista: miLis ta = [] miLis ta . appe nd (1 ) miLis ta . appe nd (2 ) miLis ta . appe nd (3 ) miLis ta . appe nd (4 ) miLis ta . appe nd (5 ) print ( m i L i s t a )
El resultado se muestra en la figura 5.1: Para conocer el largo (n´umero de elementos que hay almacenados en la lista) al igual que en strings ocupamos la funci´ on len(lista). miLis ta = [] miLis ta . appe nd (1 )
28
Figura 6.1: adherir elementos a una lista. miLis ta . appe nd (2 ) miLis ta . appe nd (3 ) miLis ta . appe nd (4 ) miLis ta . appe nd (5 ) a = le n ( l i s t a ) # El v al or d e a e s 5 p ue s t ie ne 5 e le me nt os a lm ac en ad os
Una vez inicializada la lista podemos acceder al i-´esimo elemento de la misma manera que a un string, es decir lista[i]: miLis ta = [] miLis ta . appe nd (1 ) miLis ta . appe nd (2 ) miLis ta . appe nd (3 ) miLis ta . appe nd (4 ) miLis ta . appe nd (5 ) print (miLista[0]) print (miLista[3])
Donde cabe destacar que el primer elemento est´a en la posici´o n 0 y el ´ultimo en la posici´on len(lista) − 1. El resultado de lo anterior es el siguiente:
Figura 6.2: acceder al i-´esimo elemento.
29
A diferencia de otros lenguajes, es posible adjuntar a una lista valores de distintos tipos. Por ejemplo en una lista podemos guardar valores float, int, string entre los otros que conocemos. Cabe destacar que la lista es una estructura din´ amica ya que su largo no es fijo. Bajo este contexto no se debe confundir a la lista con otra estructura de datos llamada arreglo, la que tiene un comportamiento similiar, pero su largo (cantidad de “casilleros” para almacenar informaci´on) es fijo despu´ es de su creaci´on, sin embargo, es posible modificar lo que tenga el t´ ermino i-´esimo del arreglo. En Python existe adem´as otro tipo llamado tupla, el que consta de informaci´on que no necesariamente es del mismo tipo, pero tiene un largo fijo. Adem´as no es posible modificar los valores de la tupla luego de que esta fue creada. Queda a criterio del lector buscar informaci´on sobre estas dos estructuras de datos mencionadas. Ejemplo 6.1 Cree una bit´acora en Python en el que sea posible pedir al usuario la fecha de un suceso y un string que diga el suceso que desea guardar. Para esto haremos un men´u para ver si el usuario quiere agregar una nota o verlas todas. b i ta c or a = [ ] op = 0 while o p ! = " 3 ": op = input (" Q ue d e se a h a ce r \ n1 ) A g re g ar n o ta \ n 2 ) L e er N o ta s \ n3 ) S a li r \ n ") if o p = = " 1" : # S e s u po n e q u e e l u s ua r io i n gr e sa b i en e s to s d a to s y ea r = input ( " Y e ar ? : " ) mon th = input ( " M o nt h ? : " ) d ay = input (" D ay ? : ") s u ce s o = input (" I n g re s e e l s u ce s o : " ) s = y ea r+" / "+ m o n t h +"/ " + d a y +": "+suceso bitacora.append(s) if o p = = " 2" : fo r i in range (0 , le n (bitacora)): print ( b i t a c o r a [ i ] ) elif op!= " 3" an d op!= " 2 " an d op!= " 1" : print ( " I n g r e so e q u iv o c ad o , \ i n t e n t e d e n u e vo " )
6.2.
Utilidades y funciones para listas unidimensionales
Aparte de len() y append() existen otras funciones y utilidades que hay que tener presentes sobre listas: Para obtener parte de una lista debemos usar lista[x:y] de la misma forma que en strings. Esto no modifica la lista original. l1=[1,2,3,4,5,6,7,8,9,10] l2=l1[5:] # l 2 t i en e l os v a lo r es : [ 6 , 7 ,8 , 9 , 10 ]
Para transformar un string a una lista de caracteres podemos usar list(): s="hola" l i st a = list (s ) # l i st a t i en e l os v a lo r es : [ " h " ," o " , "l " , "a " ]
Esto u ´ ltimo tambi´en funciona para pasar un valor de tipo range() a una lista de n´umeros. Esto se muestra en 30
la figura 5.3.
Figura 6.3: range vs lista. lista.remove(elemento): Elimina la primera aparaci´on de “elemento” en la lista. Si no existe se nos lanza un error. s="hola" l i st a = list (s ) lista.remove( " h ") # l i st a a h or a t i en e l os v a lo r es : [ " o " ," l " ," a " ]
Si queremos borrar el i-´esimo elemento de la lista debemos usar del lista[i]: a = [ 1 ,1 , 2 , 3 ,4 , 5 , 2 ,1 0] de l a[ le n (a)-2] # Aho ra a es [1 , 1 , 2 , 3 , 4 , 5 , 1 0]
Si tenemos dos listas l1 y l2, unimos las listas con el operador +. Un ejemplo es: a = [ 1 ,2 , 3] b = [ 4 ,5 , 6] c = a+b #c es [1, 2, 3, 4, 5, 6]
lista.index(elemento): retorna el entero en el que est´a la primera aparici´on de “elemento” en la lista. Si “elemento” no existe en la lista obtendremos error. a = "holah" b = a . in de x ("h " ) #b es 0
lista.count(elemento): retorna la cantidad de veces que “elemento” se encuentra en la lista.
31
a b c d e #b #c #d #e
= = = = =
[ 1 ,1 , 2 , 2 ,2 , 3 , 4 ,5 , 5 , 5] a . c ou n t ( 1) a . c ou n t ( 3) a . c ou n t ( 5) a . c ou n t ( 6) es es es es
2 1 3 0
string.split(string2): retorna una lista de string en la que que cada se borr´o todas las apariciones de string2, y se hizo una lista con cada elemento que no fue eliminado. El string original no se ve modificado. s="Soy|un|string|con|rayas" b = s . sp li t ("| " ) # b e s [ ’ So y ’ , ’ un ’ , ’ s tr in g ’ , ’ co n ’ , ’ r ay as ’ ] s2 =" Yo no se q ue s oy " b 2 = s 2 . sp l it ( " n o ") # b e s [ ’ Yo ’ , ’ s e q u e s oy ’ ]
6.3.
For
Ya hab´ıamos usado el for anteriormente como una herramienta para realizar iteraciones usando “range”. Ahora que conocemos las listas, podemos decir que este es un tipo “iterable”, es decir, podemos realizar acciones para cada uno de los valores almacenados. Cuando hacemos: fo r < v a r i a b l e l o ca l > i n < l i st a > : # G r up o d e i n s tr u cc i o ne s a e j ec u ta r # P ue de n u sa r o n o a l a v ar ia bl e l oc al
Lo que hacemos es tomar uno a uno los valores almacenados en lista, le damos el nombre de “variable local” mientras est´e en la iteraci´on y ejecutamos acciones. As´ı: s =[ " p a l a b r a 1 "," p a l a b r a 2 " ,..., " p a l a b r a n "] fo r p a la b ra i n s : print ( p a l a b r a ) # E s te p r og r am a i m pr i me d es d e p a la b ra 1 a p a la b ra n
Imprime todas las palabras de la lista s asign´andoles momentaneamente el nombre palabra mientras pasen por la iteraci´ on. Notemos que palabra va tomando los valores desde “palabra1” hasta “palabran”. Esto ´ultimo es muy distinto a: s =[ " p a l a b r a 1 "," p a l a b r a 2 " ,..., " p a l a b r a n "] fo r i in range (0 , le n (s)): print ( i) # E s te p r og r am a i m pr i me l os n u me r os d e sd e 0 h a st a n - 1 # N o ta m os q ue s on n p a la b ra s
32
Ya que aqu´ı la variable local i toma los valores num´ericos entre 0 y n − 1. Si quisieramos imprimir las palabras usando range en el for deber´ıamos: s =[ " p a l a b r a 1 "," p a l a b r a 2 " ,..., " p a l a b r a n "] fo r i in range (0 , le n (s)): print (s[i]) # E s te p r og r am a v u el v e a i m pr i mi r l as p a la b ra s
6.4.
Ordenamiento
Python posee una funci´on de ordenamiento llamada sort() que es capaz de ordenar alfab´ eticamente ( seg´ u n la tabla ASCII) una lista de strings y de menor a mayor un grupo de n´umeros. ¿Pero si queremos hacer otro tipo de ordenamiento?. Existen diversos algoritmos que sirven para ordenar. A continuaci´on se van a detallar dos de estos algoritmos esperando que el lector busque otros y mientras tanto descubra por si mismo como implementarlos en Python. Bubble Sort: Algoritmo de ordenamiento que se para en un t´ermino y ve el t´ermino siguiente. Si est´an en orden incorrecto los voltea. Es necesario recorrer desde el principio hasta el final una lista muchas veces para lograr una lista completamente ordenada. Insertion Sort: Se toma el primer elemento y se fija. Luego se escoje el menor de todos los dem´as y se u ´bica antes o despu´ es (dependiendo si es mayor o menor) del t´ ermino original. Luego tenemos dos elementos ordenados. Ahora se vuelven a tomar los restantes, y se escoge el menor y se ordena respecto a los primeros dos (que ten´ıamos fijos y ya estaban ordenados). En general tenemos elementos ordenados y otros que faltan por ordenar. Se toma el menor de los que falta por ordenar y se ubica en su posici´on correspondiente en los elementos ya ordenados.Se hace esto hasta obtener una lista completamente ordenada.
6.5.
Listas bidimensionales
Las listas bidimensionales son listas de listas. Para inicializar una es posible crear una lista vac´ıa e ingresar a ella m´ as listas. Es posible hacer listas multidimensionales pero en este texto se detallaran hasta las listas bidimensionales: s=[] a=[1,2] b=[3,4] s.append(a) s.append(b) # A h or a s t i en e l os v a lo r es [ [1 , 2 ] , [3 , 4 ]]
Sea listaBid una lista bidimensional. Supongamos que esta se compone de n listas. Si quiero acceder al i-´esimo elemento de la j-´esima lista con 0 ≤ j < n debo hacer lo siguiente: listaBid[j][i]
Notamos que me muevo primero a la j-´esima lista, y en esta busco la i-´esima variable. Esta es posible almacenarla en una variable. Notemos que es posible interpretar estos arreglos como matrices, ya que cada arreglo interior puede
33
corresponder a una fila, y si todos estos arreglos interiores tienen el mismo largo, este largo corresponde al n´umero de columna1 .
6.6.
Valores por referencia
Supongamos que tenemos el siguiente c´odigo: a = [ 1 ,2 , 3] b = a
Luego si edito un valor en b, este tambi´ en se editar´a en a, ya que al decir “b = a” son ahora la misma lista. Esto sucede porque las listas son tipos por referencia, es decir, no nos importan los valores, sino que sus direcciones en memoria. Hasta ahora hab´ıamos trabajado s´olo con tipos por valor. Este concepto es muy amplio y se detalla en otros cursos, por ende, ahora s´olo debemos quedarnos con que el c´odigo anterior es problem´atico. Una soluci´on es: a = [ 1 ,2 , 3] b = [] fo r i i n a : b.append(i)
Esto tambi´en pasa cuando creo una lista bidimensional a partir de la misma lista: a = [ x, x, x] b.append(a) b.append(a) b.append(a) # H a st a a h or a e l v a lo r d e a e s [ [ x, x , x ] ,[ x , x ,x ] , [x , x , x ]]
Si edito uno de los tres arreglos interiores, se editar´an los tres: a = [ x, x, x] b.append(a) b.append(a) b.append(a) b [ 0 ][ 0 ] = " o" # H a st a a h or a e l v a lo r d e a e s [ [ o, x , x ] ,[ o , x ,x ] , [o , x , x ]]
Para solucionar este problema: b=[] fo r i in range (0,3): a=[] fo r j in range (0,3): a . a p p e n d (" x" ) b.append(a)
Esto u ´ ltimo funciona ya que al inicializar en cada iteraci´on el valor de a otra vez como vac´ıo, no estoy agregando a b el mismo arreglo. 1
Es posible que el usuario los quiera leer al rev´ es, por lo que es instructivo mencionar que hay diversas formas de interpretar las listas bidimensionales y la que se muestra aqu´ı es s´olo una gu´ıa.
34
Ejemplo 6.2 Sea M una matriz de 2x2. Cree una funci´on que pida como par´ametro un arreglo bidimensional que represente a M y retorne su determinante. Interpretamos la matriz bidimensional como [[a,b],[c,d]] donde el determinante es ad − bc. de f determinante(m): a 1 = ( m [ 0 ][ 0 ]) * ( m [ 1] [ 1] ) a 2 = ( m [ 0 ][ 1 ]) * ( m [ 1] [ 0] ) d et = a1 - a 2 return de t a = float ( input ( " I ng re se a : " )) b = float ( input ( " I ng re se b : " )) c = float ( input ( " I ng re se c : " )) d = float ( input ( " I ng re se d : " )) p r im e ra F il a = [ a , b] s e gu n da F il a = [ c , d] miMatriz = [ pr im era Fi la , segundaFila ] print ( d e t e r m i n a n t e ( m i M a t r i z ) )
35
Cap´ıtulo 7
Diccionarios 7.1.
Funcionamiento de un diccionario
En computaci´on, un diccionario es una estructura de datos que nos permite insertar, eliminar y buscar elementos en ella. No nos asegura que lo que estemos guardando se mantenga ordenado, pero si nos asegura que la busqueda de un valor sea extremadamente r´apida. Lo que se almacena en un diccionario es una llave junto a su valor. En el diccionario buscaremos un elemento por su llave y se nos retornar´a el valor. Por ejemplo yo puedo almacenar la tupla (1 , ”miPalabra”), es decir la llave 1, junto al valor “miPalabra”. Si yo le pregunto al diccionario el valor asociado a la llave 1, este me contestar´a “miPalabra”. Sin embargo si yo le pregunto por “miPalabra” el diccionario no sabr´a contestarme. El diccionario que veremos a continuaci´on se conoce habitualmente como una tabla de hash. Si bien su construcci´on y funcionamiento se explican en cursos superiores, a grandes rasgos su funcionamiento es el siguiente: Cuando inicializo un diccionario, reservo un determinado n´umero de buckets (casilleros) en mi memoria. Cada uno tiene un n´umero de bucket asociado. Cuando quiero almacenar una llave ingreso su valor a una funci´on h(x) que me retorna un n´umero entero, el que me indicar´a el n´ umero del bucket en que guardar´e el valor. Si el bucket estaba ocupado, comienzo a generar una lista con todos los valores que se van acumulando. Mientras m´as valores acumule en un casillero, m´as lento se volver´a mi diccionario. Cuando quiero buscar el elemento por su llave, calculo su funci´on h(x) que me dir´a el casillero en el que est´a. Luego me muevo en la lista respectiva hasta encontrar el valor exacto. Luego lo retorno. Cuando quiero eliminar un elemento, realizo la misma acci´on que en el punto anterior, s´olo que en vez de retornar el elemento, lo elimino. En este cap´ıtulo no implementaremos nuestro propio diccionario, sino que aprenderemos a usar el que viene implementado por Pyrhon.
7.2.
Uso del diccionario
En Python tenemos dos formas de instanciar un nuevo diccionario. La primera de ellas es usando la funci´on dict(), que genera un diccionario vac´ıo:
36
miDicc ionario = dict () # L a v a ri a bl e m i Di c c io n ar i o t i en e a l ma c en a do u n n u ev o d i cc i on a ri o .
La otra forma es declarar directamente el valor de las llaves con sus respectivos valores asignados: miDicc ionario = {1 : ’ Ja me s ’ , 2: ’ Ki rk ’ , 3: ’ La rs ’ ,4 : ’ Cl if f ’ }
Independiente de la forma en la que creemos nuestro diccionario 1 , la forma de insertar, buscar y eliminar es la misma: Para insertar una llave k en nuestro diccionario asociado al valor value debemos hacer lo siguiente: mi Dicciona rio [ ke y ] = va lu e
Para eliminar la llave k con su respectivo valor asociado, debemos hacer lo siguiente de l miDiccionario[key]
Para buscar un valor value por su respectiva llave k, debemos hacer lo siguiente: a = m i Di c c io n ar i o [ k ] # A ho ra l a v ar ia bl e a t ie ne a si gn ad o e l v al or d e v al ue .
Si queremos obtener una lista con todas las llaves del diccionario la podemos obtener as´ı: l i s t a Ke y s = list ( m i D i c c i o n a r i o . k e y s ( ) ) # A h or a e n l i st a Ke y s t e ne m os u na l i st a c on t o da s l as l l av e s .
Por u ´ ltimo, si queremos consultar si una determinada llave k forma parte del diccionario, lo podemos preguntar as´ı: v ar = k i n m iD i cc io na r io # S i k f o rm a p a rt e d e m i Di c ci o na r io , v ar t o ma e l v a lo r T r ue . # S i k n o f o rm a p a rt e d e m i Di c ci o na r io , v al t o ma e l v a lo r F a ls e .
Ejemplo 7.1 Dada una lista de strings que contiene el n´umero de alumno y el nombre de un grupo de alumnos separados con un — como por ejemplo: #’123|Juan’
Cree una funci´on que reciba dicha lista y retorne un diccionario diccionario que como llave reciba un n´umero de alumno y su value sea el nombre del alumno. Luego para cada llave, imprima su value. Primero definimos la funci´on pedida: de f listaToDic(lista): d i cc R et = dict () fo r i i n l is ta : 1
Los ejemplos a continuaci´ on suponen que tenemos instanciado un diccionario llamado miDiccionario.
37
s = i . s p li t ( ’ | ’) a = in t (s[0]) b = s[1] diccRet[a]=b return diccRet
Luego, dada una lista llamada “lista” hacemos lo siguiente: d = l i st a To D ic ( l i s ta ) fo r i in list (d.keys()): print (d[i])
38
Cap´ıtulo 8
Clases 8.1.
Programaci´ on orientada a objetos
La programaci´on orientada a objetos es el paradigma de programaci´on que se basa en la interacci´on de objetos. Un ob jeto es una entidad dentro de un programa que posee un comportamiento caracter´ıstico seg´un su clase. Cuando queremos modelar comportamientos del mundo real en un programa desearemos trabajar con objetos y no s´ olo con los tipos implementados en Python. Desearemos tener nuestros propios tipos con funciones esp ec´ıficas para darles un cierto comportamiento deseado. Es necesario entonces poder instanciar objetos dentro de un programa de Python para modelar mejor los comportamientos de la realidad. Para esto necesitamos hacer uso de Clases. Las clases son la herramienta que la programaci´ on orientada a objetos (OOP) usa para trabajar.
8.2.
Crear una clase
8.2.1.
Declarar una clase
Crear una clase en Python es an´alogo a crear una planilla en la que se describe el comportamiento que tendr´an los objetos provenientes de aquella clase. Para definir una clase debemos escribir lo siguiente: class < N o m b r e d e l a c l as e > : < A qu i v a e l c o nt e ni d o d e l a c l as e i nd e nt a do >
El contenido indentado corresponde a los atributos de la clase y las funciones caracter´ısticas de la clase, que llamaremos m´ etodos, dentro de los cuales est´a el constructor, que permite instanciar objetos de la clase creada.
8.2.2.
Atributos de la clase
Cada clase debe contener ciertas variables que definen su comportamiento. Por ejemplo al crear una clase Persona esta debe poseer una variable tipo string que almacene su nombre, otra de tipo int que almacene su edad, una lista que almacene el banco y un n´umero de cuenta, entre varias otras variables. Estas variables pueden ser declaradas indentadas dentro de la clase. Siguiendo con el ejemplo de las personas: class Persona: r ut = "" ed ad = 0
39
d a t os B an c a ri o s = [ ] < R e st o d e l o s d at os >
Notamos que los atributos tienen valores de base que no indican, puesto que cuando creemos una persona, estos atributos no deben tener un valor particular, por lo que debemos entregarlos cada vez que inicialicemos un nuevo objeto de cierta clase. Es necesario entonces conocer el m´ etodo constructor.
8.2.3.
Constructor
El constructor es un m´etodo que recibe como par´ametros las variables con las que inicializaremos cada nuevo objeto. Estos par´ametros se asignan a los atributos. Debe ser declarado de la siguiente forma: class < N o m b r e d e l a C l as e > : de f _ _ i n it _ _ ( s e lf , p a r a m et r o I n gr e s a d o_ 1 , . .. , p a r a m e t r oI n g r e s a do _ n ) : s e l f . a t r i bu t o _ 1 = p a r a m e t ro I n g r e s ad o _ 1 s e l f . a t r i bu t o _ 2 = p a r a m e t ro I n g r e s ad o _ 2 #... s e l f . a t r i bu t o _ n = p a r a m e t ro I n g r e s ad o _ n < C o n t e n id o a d i c i on a l de l constructo r > < C o nt e ni d o d e l a c la se >
Es necesario notar que: Los atributos toman el valor de los parametros ingresados y no necesariamente deben tener el mismo nombre. Los par´ametros no necesariamente tienen que ser asignados a atributos. Se puede trabajar dentro del constructor con ellos (como en una funci´on normal) y asignar alg´ un otro valor a los atributos. Los atributos de la clase que van a recibir una asignaci´on de alg´ un valor deben venir con un self. como se mostr´ o anteriormente. Si a un atributo al que se le asigna un valor dentro del constructor no es definido en la clase, este se crear´a autom´ aticamente, por lo que los atributos asignados dentro del constructor no requieren ser declarados en la clase. Si continuamos con el ejemplo de las personas: class Persona: de f _ _ i n it _ _ ( s e lf , n o mb r e , e d a d In g r e sa d a , b a nc o , n u m e r oC u e n t a ) : s e lf . n o m br e = n o mb r e s e l f . e d ad = e d a d I n gr e s a d a l is ta = [ ] lista.append(banco) lista.append(numeroCuenta) s e l f . d a t o s Ba n c a r i o s = l i s ta < C o nt e ni d o a d ic i on a l d e l a c la se >
Es necesario destacar que un objeto de la clase persona posee como atributos (variables que lo caracterizan) a nombre , edad y datosBancarios . Los atributos definidos no requieren tener el mismo nombre de los par´ametros que recibe la funci´on. Se muestra en el ejemplo que el m´etodo recibe un “nombre” que se asigna al atributo “nombre”. Pero tambi´en el m´etodo recibe una “edadIngresada” a pesar de que el atributo de la clase se llame “edad”.
40
8.2.4.
Instanciar un objeto en el programa
Para instanciar un objeto de cierta clase en el programa se hace de la siguiente manera: class miClase: < C o nt e ni d o d e l a c la se > # I n ic i o d el p r og r am a miObjeto = miCla se ( par am et ro_ 1 , .. . , parametro_n )
En donde miObjeto es un objeto de la clase miClase . Es necesario destacar que el constructor recibe a self y los par´ametros, sin embargo, para instanciar un objeto en el programa, debemos ingresar s´olo los par´ametros. Si queremos usar en el programa un atributo del objeto tenemos que escribir lo siguiente: class miClase: < C o nt e ni d o d e l a c la se >
# I n ic i o d el p r og r am a miObjeto = miCla se ( par am et ro_ 1 , .. . , parametro_n ) v a r = m i O b je t o . a t r i b u t oX # A s i gn a mo s e l v a lo r d el " a t r ib u to X " a l a v a ri a bl e v ar #... miObjeto . atributoX = val or # E l a t ri b ut o X d e m i Ob j et o t o ma u n n u ev o v a lo r
Para ejemplificar, continuaremos el ejemplo de las personas: class Persona: de f _ _ i n it _ _ ( s e lf , n o mb r e , e d a d In g r e sa d a , b a nc o , n u m e r oC u e n t a ) : s e lf . n o m br e = n o mb r e s e l f . e d ad = e d a d I n gr e s a d a l is ta = [ ] lista.append(banco) lista.append(numeroCuenta) s e l f . d a t o s Ba n c a r i o s = l i s ta # < C o nt e ni d o a d ic i on a l d e l a c la se > # I n ic i o d el p r og r am a # E s ta l i ne a c r ea u n n u ev o o b je t o t ip o p e rs o na mi Persona = Per sona (" J u a n " , 30 , " B a nc o E s t ad o " ," 0 0 0 0 0 0 0 1 ") print ( m i P e r s o n a . n o m b r e ) print ( m i P e r s o n a . e d a d ) print ( m i P e r s o n a . d a t o s B a n c a r i o s )
El resultado de lo anterior es el siguiente:
41
Figura 8.1: imprimir los datos de “Juan”.
8.2.5.
Self
Cada m´etodo definido en una clase debe recibir un primer par´ametro que puede llevar cualquier nombre, pero es una buena pr´actica llamarlo self . Este par´ametro nos sirve para cuando deseemos referenciar en alguno de los m´ etodos definidos en la clase a los atributos que contiene el objeto, o al objeto mismo. En el constructor, cuando quer´ıamos asignar valores al atributo del objeto deb´ıamos utilizar el self. Si no hubiesemos usado el self, el programa crear´ıa una variable que no quedar´ıa almacenada en el ob jeto. En el ejemplo anterior, la variable lista no queda almacenada en el objeto persona, pero si se almacenar´a el atributo datosBancarios .
8.2.6.
M´ etodos
Los m´ etodos son funciones que se definen indentadas en la declaraci´ on de la clase como las que ya conocemos, pero la diferencia es que cuando queramos llamarlas en el programa, necesitamos de un objeto de su clase para ser utilizadas. Su definici´ on es de la siguiente manera: class < N o m b r e d e l a C l as e > : de f _ _ i n it _ _ ( s e lf , p a r a m et r o I n gr e s a d o_ 1 , . .. , p a r a m e t r oI n g r e s a do _ n ) : s e l f . a t r i bu t o _ 1 = p a r a m e t ro I n g r e s ad o _ 1 s e l f . a t r i bu t o _ 2 = p a r a m e t ro I n g r e s ad o _ 2 #... s e l f . a t r i bu t o _ n = p a r a m e t ro I n g r e s ad o _ n < C o n t e n id o a d i c i on a l de l constructo r > de f metodo_1(self , parametro_1 ,...,parametro_n ): de f metodo_2(self , parametro_1 ,...,parametro_n ): #...
Cuando se haga un llamado a un m´etodo se debe haber antes instanciado un objeto de aquella clase. Luego hay que escribir objeto.m´etodo(par´ ametros) como se muestra a continuaci´on:
42
class miClase: < C o nt e ni d o d e l a c la se > de f metodo_1(self , parametro_1 ,...,parametro_n ):
#... miObjeto = miCla se ( par am et ro_ 1 , .. . , parametro_n ) miobjeto . metodo _1 ( parametroIngresado_1 , .. . , pa rame tro Ingr esa do_2 )
Continuaremos con el ejemplo de las personas. Definirimos un m´ etodo que representa el cumplea˜nos de la persona, otro que cambie los datos bancarios, y por ´ultimo, un m´ etodo que imprime todos los datos en la consola: class Persona: de f _ _ i n it _ _ ( s e lf , n o mb r e , e d a d In g r e sa d a , b a nc o , n u m e r oC u e n t a ) : s e lf . n o m br e = n o mb r e s e l f . e d ad = e d a d I n gr e s a d a l is ta = [ ] lista.append(banco) lista.append(numeroCuenta) s e l f . d a t o s Ba n c a r i o s = l i s ta de f cumpleFeliz(self): # N o ta m os q ue e st e m e to d o n o r e ci b e p a ra m et r o s el f . ed ad = s el f . ed ad + 1 de f cambioDeBanco( self,bancoNuevo ,cuentaNueva ): s e l f . d a t o s Ba n c a r i o s [ 0 ] = b a n c o Nu e v o s e l f . d a t o s Ba n c a r i o s [ 1 ] = c u e n t aN u e v a de f imprimirDatos(self): print ( " N o mb r e : "+ s e l f . n o m b r e ) print ( " E da d : " + st r (self.edad)) print ( " B a nc o : " + s e l f . d a t o s B a n c a r i o s [ 0 ] ) print ( " C u en t a : "+ s e l f . d a t o s B a n c a r i o s [ 1 ] ) mi Persona = Per sona (" J u a n " ,30, " B a n c o E s t a d o " ," 0 0 0 0 0 0 0 1 ") mi Persona . impr imirDato s () mi Persona . cumpleFeliz () mi Persona . camb ioDeBanc o ( " B a n c o S a n t a nd e r " ," 0 0 0 0 0 0 0 2 ") mi Persona . impr imirDato s ()
El resultado de lo anterior se puede apreciar en la figura 6.2. El contenido de clases es m´as extenso, por lo que es recomendado para el lector ahondar en esta materia. Ejercicio Propuesto 8.1 Recientemente fueron lanzados al mercado nuevos videojuegos de la saga Pokemon. Como usted no quiere ser menos, se ha propuesto comenzar a programar su propio Pokemon. Para esto debe comenzar modelando las clases Pokemon y Ataque Pokemon. La primera debe contener como atributos la vida m´axima del Pokemon, su vida actual, su tipo y una lista de ataques (que contendr´a objetos de clase Ataque Pokemon). La clase Ataque Pokemon debe contener el tipo del ataque y el da˜no que realiza. Luego debe ser capaz de programar
43
Figura 8.2: utilizaci´ on de m´etodos. una batalla Pokemon1 . Todo lo dem´as queda a criterio del programador. Se propone hacer el juego lo m´as fluido posible.
1
Se recomienda fuertemente que la batalla sea modelada con la materia de clases, ya sea como m´ etodo o una clase propia. Si no se conoce el juego puede buscar en la web algunas referencias.
44
Cap´ıtulo 9
Archivos 9.1.
¿Por qu´ e guardar datos?
Hasta ahora todo lo que hemos programado no es persistente en el tiempo. Es decir, una vez cerrado el programa, toda interacci´on con el usuario no tendr´a efecto en las posteriores ejecuciones. Pero ¿Qu´e pasa si queremos guardar permanentemente los datos entregados por nuestro programa?. Para esto se hace necesario hacer uso de manejo de archivos. En este texto nos enfocaremos a leer archivos de texto plano (archivos con extensi´on .txt).
9.2.
Ruta de un archivo
La ruta (o path) de un archivo es su ubicaci´on en el computador. Esta puede ser una ruta relativa o absoluta. Una ruta absoluta indica una ruta independiente de la ubicaci´on del .py que estamos ejecutando, mientras que una ruta relativa depende de la ubicaci´on del .py que ejecutamos. Para el manejo de rutas se hace necesario importar el m´ odulo os. Si el lector desea ahondar en este tema, puede buscar informaci´on acerca de esto en internet. Nosotros s´ olo trabajaremos con archivos que se encuentren en la misma carpeta que nuestro .py mediante rutas relativas.
9.3.
Leer un archivo de texto
Para leer un archivo de texto necesitamos hacer uso de la funci´on open en modo lectura. Esta funci´on open recibe como par´ametros el path del archivo (ruta en donde se encuentra ubicado) y el modo (lectura o escritura). Esta funci´ on retorna un objeto tipo file que debemos almacenar en una variable. Para abrir un archivo en modo lectura debemos escribir lo siguiente: mi Archivo = ope n (< Nomb re de l archivo >, "r ")
En donde Nombre del archivo es el nombre del archivo que queremos cargar que se encuentra en la misma carpeta que nuestro programa. Este debe incluir la extensi´on .txt Ahora bien para leer el objeto tipo file que cargamos podemos usar la funci´on readline o readlines readline: Esta funci´on siempre lee la primera l´ınea del archivo ya cargado (Identifica una l´ınea segun los saltos de l´ınea) y la retorna como string(generalmente con el fin de almacenarlo en una variable). Esta l´ınea se elimina del archivo cargado (No del archivo original) con el fin de seguir us´andola para cargar el archivo. readlines: Esta funci´on lee todas l´ıneas, las retorna como una lista de strings (generalmente para almacenarlas en otra variable) y las borra del archivo cargado. Los string retornados en la lista si tienen los salto de l´ınea. Para extraerlos es posible cortarlos como ya lo vimos en el cap´ıtulo de strings. Es recomendado usar esta
45
funci´ on ya que deja todo almacenado en una sola lista, y es m´as sencillo trabajar sobre listas que sobre objetos tipo file . Ejemplo 9.1 Dado el siguiente archivo de extensi´on .txt llamado archivo1.txt : Hola, so y un archivo.
Imprima en el shell de Python el contenido del archivo como un solo string sin saltos de l´ınea. Cabe destacar que el archivo tiene un espacio al final de las tres primeras l´ıneas, por lo que no hay que agregarlo. Seg´ un lo descrito anteriormennte, una soluci´on es la que se presenta a continuaci´on. El resultado del shell se puede ver en la figura 7.1: mi Archivo = ope n (" a r c h i v o 1 . t x t ","r " ) s= " " l i n e a s De l A r c h i vo = m i A r c hi v o . r e a d l i n es ( ) print ( l i n e a s D e l A r c h i v o ) # E st o s ir ve p ar a v er q ue v al or t om a l a v ar ia bl e fo r c a s i ll e r o i n l i n e a s D el A r c h i v o : s = s + c as il le ro [ 0: le n ( c a s i l l e r o ) - 1 ] print ( s) # El s al to d e l in ea \ n e s u n c ar ac te r
Figura 9.1: lectura de archivos.
9.4.
Escribir un archivo .txt
9.4.1.
Modo write
Para escribir un archivo .txt en modo write debemos crear un objeto tipo file con la funci´on open con el par´ametro de modo como “w”: mi Archivo = ope n (< Nomb re de l archivo >, "w ")
Si el archivo no existe, Python lo crear´a. Si el archivo ya existe se borrar´ a y se comenzar´ a a escribir uno nuevo. Ahora para comenzar la escritura debemos usar la funci´on write. En el siguiente ejemplo: mi Archivo = ope n (" a r c h i v o . t x t "," w" ) mi Archivo . wri te ( stri ng )
46
Estamos escribiendo un archivo desde el principio que se ubica en la misma carpeta de nuestro programa y se llama archivo.txt . Estamos escribiendo el string que ingresamos como par´ametro a la funci´on write . Si queremos saltar de l´ınea debemos usar el caracter de salto de l´ınea. Cada vez que terminemos de escribir el archivo debemos usar la funci´on close() para cerrar el objeto tipo file que instanciamos. mi Archivo = ope n (" a r c h i v o . t x t "," w" ) mi Archivo . wri te ( stri ng ) mi Archivo . clo se ()
Ejemplo 9.2 Escriba el archivo del ejemplo 7.1: Hola, so y un archivo.
Usando lo la funci´on write. Recuerde que el archivo se llama “archivo1.txt” y debe estar contenido en la misma carpeta que nuestro programa. Una soluci´ on propuesta es la siguiente: mi Archivo = ope n (" a r c h i v o 8 0 0 0 . t x t ","w " ) mi Archivo . wri te ( " H ol a , \ n ") mi Archivo . wri te ( " s oy \ n ") mi Archivo . wri te ( " un \ n ") mi Archivo . wri te ( " a r c h i v o . ") mi Archivo . clo se ()
9.4.2.
Modo append
Funciona de la misma manera que el modo write, pero la diferencia es que si el archivo ya existe no lo crea otra vez, y comienza a escribir sobre ´el. Para esto se debe usar la funci´on open con el par´ametro de modo como “a”: mi Archivo = ope n (" a r c h i v o . t x t "," a" ) mi Archivo . wri te ( stri ng ) mi Archivo . clo se ()
47
Cap´ıtulo 10
Recursi´ on 10.1.
Definir una funci´ on recursiva
En ciencias de la computaci´on, la recursi´on es un m´ etodo de resoluci´on de problemas basado en la capacidad de una funci´on de llamarse a si misma en su definici´on, con el objetivo de divir un problema grande, en problemas peque˜ nos. Para su finalizaci´ on es necesario establecer una condici´ on de t´ermino de la recursi´on. En t´erminos generales una recursi´on se escribe como: de f funcion_recursiva (var_1 ,...,var_n ): if var_booleana: # C a s o b a se else : # L l a m a d a r e c u r si v a
Ejemplo 10.1 La funci´on factorial de n (n!) se defina para los naturales como 1 si n = 0 y n(n − 1)! en otro caso. Defina la funci´on recursiva en Python que calcule el factorial de un n´umero: Usamos la llamada recursiva si n no es 0: de f factorial(n): if n = = 0 : return 1 else : return n * f a ct o ri a l ( n - 1 )
10.2.
Ejemplos de funciones recursivas
10.2.1.
Quicksort
Quicksort es un ordenamiento recursivo que divide una lista en sublistas y se ordenan de la siguiente forma: Elegir un elemento de la lista que se denominar´a pivote. Dejar todos los elementos menores que ´el a un lado, y todos los mayores que el pivote al otro. Obtenemos dos sublistas. Una de todos los elementos de la izquierda, y otra de todos los elementos de la derecha. 48
Repetir recursivamente el proceso para cada sublista mientras tenga m´as de un elemento. Una forma propuesta de implementar este algoritmo en Python es la siguiente: de f sort(lista): men ores = [] i gu al es = [ ] may ores = [] if le n ( l is ta ) > 1 : p i vo t = l i st a [ 0] fo r x i n l is ta : if x < p iv ot : menor es . appe nd (x ) if x = = p iv ot : iguales.append(x) if x > p iv ot : mayor es . appe nd (x ) return s o r t ( m e n or e s ) + s o r t ( i g u a le s ) + s o r t ( m a y o r es ) # El o pe ra do r + u ne l as t re s l is ta s . O cu pa mo s l a m is ma f un ci on e n c ad a s ub li st a else : return lista
Notamos que sort es una funci´on que recibe como par´ametro una lista. En el inicio se generan tres listas auxiliares que almacenar´an los menores, los mayores y los iguales al pivote, que siempre ser´a el primer elemento de cada una de las sublistas. Luego de llenar estas tres listas auxiliares con los elementos correspondientes, debemos volver a llamar a la funci´on sort en cada una de ellas. En el ejemplo anterior, debemos notar que lista es el par´ametro ingresado, por lo que la l´ınea que dice “return lista”, esta retornando los valores de las sublistas menores, iguales o mayores, cuando posean s´olo un elemento. Es una buena idea mirar alg´un video que muestre este ordenamiento de manera gr´afica para que quede m´as claro.
10.2.2.
Permutaci´ on de Strings
Este problema consiste en tomar un string e imprimir todas sus posibles permutaciones. Es decir, todos los strings que se pueden formar usando los caracteres del string original. # F u nc i on q ue e l im i na e l i - e s i mo c a ra c te r d e u n s t ri n g . de f eliminar(s,i): if i = = 0 : return s[1:] elif i == le n (s)-1: return s [: le n (s)-1] else : return s [ : i ] + s [ i + 1 : ] de f permutar(s,perm): if le n ( p er m ) = = 1 : # Si e l l ar go d el s tr in g p er m e s 1 , l a r ec ur si on t er mi na . print ( s + p e r m ) else : fo r i in range (0 , le n (perm)): # T om a e l c ar ac te r y l o p as a s1=s+perm[i] s2=eliminar(perm,i) permutar(s1,s2)
49
de f llamar_permutar(s): permutar( " " ,s)
En este problema usamos una estrategia habitual. Se define una funci´on recursiva que recibe dos par´ametros, y otra funci´ on que sirve para iniciar la recursi´on, que fija uno de los par´ametros de la funci´on recursiva y recibe el input. La funci´on permutar recibe un string ya permutado s y otro por permutar perm. Dentro del for de la funci´on permutar , lo que se hace es tomar de a uno los caracteres por permutar, y concatenarlos con el strings ya permutado. Por ejemplo si el input es abc , en la primera llamada de permutar esta funci´on se llamar´ a recursivamente tres veces: # L a l l am a da d e p e rm u ta r ( "" , " a bc " ) l l am a a : permutar( " a " ," b c ") permutar( " b " ," a c ") permutar( " c " ," a b ")
Para cada uno de estas llamadas a permutar se vuelve a ejecutar el caso recursivo: # L a l l am a da d e p e rm u ta r ( " a " ," b c ") l l am a a : permutar( " a b " ,"c ") permutar( " a c " ,"b ") # L a l l am a da d e p e rm u ta r ( " b " ," a c ") l l am a a : permutar( " b a " ,"c ") permutar( " b c " ,"a ") # L a l l am a da d e p e rm u ta r ( " c " ," a b ") l l am a a : permutar( " c a " ,"b ") permutar( " c b " ,"a ")
Notamos que todas las llamadas anteriores ejecutan el caso base de la recursi´on, y cada una imprime respectivamente: ab c ac b ba c bc a ca b cb a
10.2.3.
Mergesort
Es un ordenamiento recursivo que se basa en la estrategia ”Dividir para conquistar”. La idea es dividir una lista en trozos e ir ordenando por segmentos del mismo tama˜no. Por ejemplo si queremos ordenar la siguiente lista de menor a mayor: l = [ 23 , 4 , 30 , 7 , 10 , 1 1 ,0 ]
La dividimos: [23][4][30][7][10][11][0]
Y ordenamos de a pares: [4,23][7,30][10,11][0]
50
Luego formamos las siguientes sub-listas: [4,7,23,30][0,10,11]
Para hacer esto se van tomando los primeros elementos de las sublistas anteriores. Por ejemplo para ordenar este segmento: # T e ne m os d os s ub - l i s t as : [4,23][7,30] # C r ea m os u na l i st a r e su l t an t e v a ci a : [4,23][7,30] [] # P as am os a e ll a e l e le me nt o m en or e nt re 4 y 7 : [23][7,30] [4 ] # L ue go e nt re 2 3 y 7 : [23][30] [4,7] # L ue go e nt re 2 3 y 3 0: [][30] [4,7,23] # L u eg o e l e l em e nt o r e st a nt e : [] [4,7,23,30]
Una implementaci´on del algoritmo es la siguiente: # O r d e n a m i en t o r e c u r si v o c o n m e r g e s o r t de f merge_sort(lista): if le n ( l i s t a ) < =1 : return lista else : l i st a _ iz q u ie r d a = [ ] l i st a _ de r ec h a = [ ] med io = le n (lista)//2 fo r i in range (0,medio): lista_izquierda.append(lista[i]) fo r j in range ( m e d i o , le n (lista)): lista_derecha.append(lista[j]) l i s t a _ iz q u i e r d a = m e r g e _s o r t ( l i s t a _ i z q ui e r d a ) l i s t a _ de r e c h a = m e r g e _s o r t ( l i s t a _ d e re c h a ) return merge(lista_izquierda ,lista_derech a) de f merge(lista_izquierda ,lista_derech a): l i s ta _ re t o rn o = [ ] while le n ( l i s t a _ i z q u i e r d a ) > 0 or le n ( l i s t a _ d e r e c h a ) > 0 : if le n ( l i s t a _ i z q u i e r d a ) > 0 an d le n ( l i s t a _ d e r e c h a ) > 0 : if l i s t a _ i zq u i e r d a [ 0 ] < = l i s t a _ de r e c h a [ 0 ] : lista_retorno.append(lista_izquierda[0]) de l lista_izquierda[0] else : lista_retorno.append(lista_derecha[0]) de l lista_derecha[0]
51
elif le n ( l i s t a _ i z q u i e r d a ) > 0 : l i s t a _ re t o r n o . a p p e nd ( l i s t a _ i z q u i e rd a [ 0 ] ) de l lista_izquierda[0] elif le n ( l i s t a _ d e r e c h a ) > 0 : lista_retorno.append(lista_derecha[0]) de l lista_derecha[0] return lista_retorno
La funci´on merge sort es recursiva. Va dividiendo en sublistas la lista original para luego ejecutarse a si misma en estas dos sublistas. Este paso se hace hasta dejar las sublistas de tam˜no 1. Luego las listas se van juntando nuevamente quedando ordenadas seg´un la funci´on merge.
52
Cap´ıtulo 11
Simulaci´ on 11.1.
¿Para qu´ e simular?
Hasta ahora hab´ıamos utilizado la programaci´on como una herramienta funcional. Dado un tipo input, gener´abamos un programa capaz de computar algo en base a ´el para luego generar un output. Si bien esto es ´util, podemos hacer muchas m´as cosas con la programaci´on, como por ejemplo simular un el comportamiento sistema mediante el uso de variables aleatorias sin tener que implementarlo en el mundo real. Con esto, podemo conocer los puntos d´ebiles del sistema, nos permite realizar un an´alisis de sensibilidad a las variables involucradas y tambi´ en tomar decisiones en torno a las estad´ısticas obtenidas. Para simular no hay una receta absoluta, simplemente debemos aplicar lo aprendido hasta ahora para intentar resolver un problema con cierto grado de seguridad. A grandes rasgos lo que debemos hacer es: Identificar las entidades que realizan acciones de interes en el sistema. Hacerlos interactuar a trav´es del tiempo. Llevar estad´ısticas almacenadas en variables. Para tener una mayor seguridad de los resultados obtenidos, es posible ejecutar la simulaci´on varias veces, y calcular promedios de las estad´ısticas recogidas.
11.2.
Ejemplos de simulaci´ on
11.2.1.
Ataque Zombie
Un ataque zombie afecta a una ciudad aislada. La cura tardar´a 10 d´ıas en ser elaborada, pero s´olo es factible de usar si hay menos de un cuarto de la poblaci´on afectada. En la ciudad viven 200000 personas y existen 500 zombies. Cada zombie tiene una probabilidad p (n´ umero entre 0 y 1) de realizar un ataque por d´ıa. En cada ataque son infectadas una o dos personas (el n´umero de infectados es aleatorio). Nos interesa saber que decisi´on tomar (correr o intentar buscar la cura) seg´un el valor de p. import random class ZombieAttack: de f __init__(self,p): s e l f . p e r so n a s = 2 0 0 0 00
53
s el f . z o mb i es = 5 00 s el f . p r ob a bi l i da d = p s el f . b i ta c or a = [ ] de f iteracion(self,j): c =0 fo r i in range ( s e l f . z o m b i e s ) : a = r a nd o m . u ni f or m ( 0 , 1) if a < s e l f . p r o b a b i l i d a d : b = r a nd o m . r an d in t ( 1 , 2) if s el f . p e rs o na s - b > 0: s e lf . p e r so n as - = b s e lf . z o m bi e s + = b c += b else : s e l f . z o m bi e s + = s e l f . p e r s on a s c + = s e lf . p e r so n as s e lf . p e r so n as = 0 s = " En el dia "+ st r (j+1)+ " f u er o n i n fe c ta d as "+ st r (c)+ " p e rs o na s " self.bitacora.append(s)
de f simulacion(self): fo r i in range (10): self.iteracion(i)
de f estadisticas(self): print ( " Z o mb i es : " , s e l f . z o m b i e s ) print ( " P e rs o na s : " , s e l f . p e r s o n a s ) fo r s i n s e lf . b i t ac o ra : print ( s ) if s el f . p e r s o n a s / 4 > s e l f . z o m bi e s : print ( " E l a b o r ar c u r a ! ") else : print ( " R un t o t he h i ll s ! ") p = in t ( input ( " I n gr e se l a p r ob a b il i da d : " )) a = Z o mb i e At t ac k ( p ) a.simulacion() a.estadisticas()
54
Cap´ıtulo 12
Ejercicios 12.1.
Cola de supermercado
Modele una cola de un servicio con una sola caja. Los clientes llegan en un tiempo aleatorio entre 7 y 12 minutos. La caja tarda en atender al cliente entre 10 y 15 minutos. La caja est´a abierta durante 480 minutos y debe correrla por 5 d´ıas. Queremos saber cuantos clientes en promedio no son atendidos en un d´ıa, cuanto se demora un cliente en promedio y el promedio de gente atendida p or d´ıa. import random class cliente: de f __init__(self): s el f . te s = 0 de f cambiarTES(self,tiempo): s el f . t es = t i em p o class servicio: de f __init__(self): s e l f . c l i e n te A c t u al = N o n e de f p a s a r C l i e nt e ( s e lf , u n C l i en t e ) : t i e m po = r a n do m . r a n d i n t ( 1 0 , 1 5) unCliente.cambiarTES(tiempo) s e l f . c l i e n te A c t u al = u n C l ie n t e class simulacion: de f __init__(self): s el f . s er v = s e rv i ci o ( ) s e l f . c l i e n te s A t e n d id o s = 0 s e l f . t i e m p oE n A t e n c io n = 0 s e l f . l i s t a De E s p e ra = [ ] p r i m e r cl i e n t e = r a n d om . r a n d i n t ( 7 , 1 2 ) s e l f . s i g u i en t e C l i e nt e = p r i m e r cl i e n t e # T i em p o e n e l q ue l l eg a ra e l s i gu i en t e c l ie n te
55
de f ejecutar(self): minut os = 48 0 while m i nu t os > = 0 : if s e l f . s i g u i e n te C l i e n t e > 0: s e l f . s i g u i en t e C l i e nt e - = 1 if s e lf . s i g u i e n t e C l i en t e = = 0 : s e l f . l i s t a De E s p e ra . a p p e n d ( c l i e n t e ( ) ) t = r a nd o m . r an d in t ( 7 , 12 ) s e l f . s i g u i en t e C l i e nt e = t # N ue v o c o nt a do r q ue e s pe r a l a l l eg a da d e u n n u ev o c l ie n t if ( s e lf . s e r v ) . c l i e n t e A ct u a l ! = N o n e : ( ( s e l f . s e rv ) . c l i e n t e A c t ua l ) . t e s - = 1 if ( ( s e lf . s e r v ) . c l i e n t e A ct u a l ) . t e s = = 0 : s e l f . c l i e n t es A t e n d i do s + = 1 ( ( s e l f . s e rv ) . c l i e n t e A c t ua l ) = N o n e if ( s e lf . s e r v ) . c l i e n t e A ct u a l = = N o n e : if le n ( s e l f . l i s t a D e E s p e r a ) > 0 : t i = ( s e l f . s e r v ) . p a s a rC l i e n t e ( s e lf . l i s t a D e E s p e ra [ 0 ] ) de l self.listaDeEspera[0] mi nu to s - =1 print ( " Q ue do e n e sp er a : "+ st r ( le n ( s e l f . l i s t a D e E s p e r a ) ) ) print ( " S e a t en d ie r on : "+ st r ( s e l f . c l i e n t e s A t e n d i d o s ) ) return st r ( le n ( s e l f . l i s t a D eE s p e r a ) ) + "| " + st r ( s e l f . c l i e n t e s A t e n d i d o s ) dia = 1 s u mL i s ta E sp e r a = 0 s u m C l i e nt e s A t e n d id o s = 0 s u mP r o mT i em p o = 0 fo r i in range (0,5): print ( " # ## D ia : " + st r (dia)+ " # ## ") mi Si m = simulacion () s = m i Si m . e j ec u ta r ( ) l = s . sp li t ("| " ) a = in t (l[0]) b = in t (l[1]) s u m Li s ta E s pe r a + = a s u m C l i e n te s A t e n d id o s + = b s u m P r o mT i e m p o + = 4 8 0 / b dia+=1 print ( s u m L i s t a E s p e r a / 5 ) print ( s u m C l i e n t e s A t e n d i d o s / 5 ) print ( s u m P r o m T i e m p o / 5 )
56
12.2.
Banco de la Plaza
Hoy en d´ıa los fraudes bancarios han crecido exponencialmenete. Muchas veces los clientes de un banco no se daban cuenta porque no ten´ıan acceso a revisar su estado de cuenta a trav´es de internet. Para dar soluci´on a este problema, el Departamento de Ciencia de la Computaci´on te ha encargado crear un programa en Python que permita llevar la administraci´ on de las cuentas corrientes de los clientes del Banco de la Plaza . El programa debe permitir almacenar clientes y sus transacciones bancarias: nombre, rut, g´ enero, balance y lista transacciones. El atributo lista transacciones a su vez est´a compuesto por tuplas de 4 elementos cada una: nombre transacci´on, fecha transacci´on, descripci´ on transacci´on y monto transaccion,de esta forma un cliente puede tener muchas transacciones registradas. El formato de la fecha es dd-mm-yyyy, donde dd es d´ıa, mm es mes y yyyy es a˜ no, ejemplo 21-03-2014. El atributo balance determina el monto inicial que un cliente tiene en su cuenta bancaria. Los tipos de transacci´on v´alidos son: Deposito, Giro y Compra. El programa debe permitir crear nuevos clientes y administrar su informaci´on. Por lo tanto, se debe contar con el siguiente men´ u principal: B i e n v en i d o a l S i s t em a de l B a nc o d e l a P la za S e l e c ci o n e u n a a c c io n : [ 1] C r ea r c l ie n te [ 2 ] M o s t ra r c l i e nt e s [ 3 ] B u s ca r c l i e n te s [ 4] A g re g ar t r an s ac c i on a u n c l ie n te [ 5 ] S a l ir
La opci´on [1] del men´ u principal debe permitir al usuario crear un nuevo cliente. La opci´on [2] del men´ u principal debe permitir desplegar todos los clientes que est´an registrados en el banco. Por ejemplo, si se han registrado 3 clientes, se debe mostrar la informaci´on completa de cada cliente: S e l e c ci o n e c l i e nt e : [ 1 ] J u l io M e ne s es , 1 . 45 6 . 27 3 - 5 , M a s cu l i no , [ ( D e p os i to , 1 5 - 0 1 - 2 01 0 , p a r a g a s to s c o mu n es , 1 00 0 ) , ( C o m pr a , 1 1 - 0 3 - 2 01 2 , z a p a to s M e rr e l , 5 0 0 00 ) ] [ 2 ] F a b i ol a R e ta m a l , 1 9 . 26 4 . 19 8 - 4 , F e m en i no , [ ( G ir o , 0 5 - 1 9 - 20 1 3 , p a ra p r es t a mo , 1 7 00 0 ) , ( G i ro , 1 1 - 0 4 - 20 1 4 , c o m p ra c a rt e r a , 3 5 0 0 00 ) ] [ 3 ] A l i ci a A l ia g a , 1 8 . 98 4 . 85 3 - 3 , F e me n i no , [ ( C o mp r a , 1 2 - 0 3 - 2 01 4 , c a r t er a L u i s G r it o n , 5 0 0) ] [ 4 ] S a l ir
La opci´on [3] Buscar del men´ u principal debe mostrar el siguiente sub-men´u: I n gr e se e l t ip o d e b u sq u ed a : [ 1] P or n o mb r e c l ie n te [ 2] P or n om br e d e c li en te y t ip o d e t ra ns a cc io n [ 3] P or f e ch a [ 4 ] S a l ir
La opci´on [1] debe preguntar por el nombre del cliente y deplegar el registro completo del cliente. La opci´on [2] debe preguntar por el nombre del cliente y el tipo de transaccion (Deposito, Giro o Compra). De esta forma, se deplegar´an todas las transacciones de cierto tipo de un cliente determinado.
57
La opci´on [3] debe mostrar la informaci´on de todos los clientes que tengan transacciones en la fecha ingresada. Es decir, el nombre del cliente, el rut y la tupla de la transacci´on con la fecha buscada La opci´on [4] del men´u principal debe permitir agregar una nueva transaccion a un cliente. Pare ellos, se debe deplegar todos los clientes, seleccionar uno de ellos y finalmente agregar la transaccion. Ejemplo, si se selecciona esta opci´on, se despliegan los cliente hasta ahora registrados: S e l e c ci o n e c l i e nt e : [ 1 ] J u l io M e ne s es , 1 . 45 6 . 27 3 - 5 , M a s cu l i no , [ ( D e p os i to , 1 5 - 0 1 - 2 01 0 , p a r a g a s to s c o mu n es , 1 00 0 ) , ( C o m pr a , 1 1 - 0 3 - 2 01 2 , z a p a to s M e rr e l , 5 0 0 00 ) ] [ 2 ] F a b i ol a R e ta m a l , 1 9 . 26 4 . 19 8 - 4 , F e m en i no , [ ( G ir o , 0 5 - 1 9 - 20 1 3 , p a ra p r es t a mo , 1 7 00 0 ) , ( G i ro , 1 1 - 0 4 - 20 1 4 , c o m p ra c a rt e r a , 3 5 0 0 00 ) ] [ 3 ] A l i ci a A l ia g a , 1 8 . 98 4 . 85 3 - 3 , F e me n i no , [ ( C o mp r a , 1 2 - 0 3 - 2 01 4 , c a r t er a L u i s G r it o n , 5 0 0) ] [ 4 ] S a l ir 2 I n g r es e t i p o t r a n s a c c i o n : C o m pr a I n g r es e f e c ha t r a n s a cc i o n : 0 1 - 0 4 - 2 01 4 I n g r es e d e s c r ip c i o n : P e r f um e C a r o li n a L e s e ra I n gr e se m o nt o d e l a t r an s a cc i on : 1 1 00 0 0 S e h a a g re g ad o u na t r an s ac c io n a l c l ie n te F a bi o la R e ta m al : [ ( G ir o , 0 5 - 1 9 - 2 01 3 , p a r a p r e st a m o , 1 7 00 0 ) , ( G i ro , 1 1 - 0 4 - 20 1 4 , c o m p ra c a rt e r a , 3 5 00 0 0 ) , ( C o m pr a , 0 1 - 0 4 - 2 01 4 , P e r f um e C a r o li n a L e se r a , 1 1 0 00 ) ]
La opci´on [5] del men´ u principal permite salir completamente del programa de Sistema Banco de la Plaza. Se te pide que crees la clase Cliente que debe contar con los siguientes atributos: Un string para el nombre del cliente Un string para el rut del cliente Un string para la fecha de la transaccion Un entero para el balance del cliente Una lista para las transacciones del cliente (recuerda que cada transacci´on ser´a una tupla con (tipo transaccion, fecha transaccion, descripcion,monto)) Adem´ as la clase cliente debe contar al menos con los siguientes m´etodos: etodo permite agregar una nueva transaccion al agregar transaccion(self, nuevatransaccion): Este m´ listado de transacciones que ya tiene un cliente. etodo retorna True si el cliente a´un tiene balance positivo, y False caso de verifica balance(self) : Este m´ tener balance negativo. etodo actualiza el balance de un cliente utilizando el par´ ametro actualiza balance(self,monto) : Este m´ monto que recibe el m´etodo. Tu programa principal debe contar con al menos las siguientes funciones: mostrar menuprincipal(): Esta funci´ on solo depliega el menu principal.
on debe deplegar todos los clientes del banco. mostrar clientes(lista clientes): Esta funci´ 58
on recibe la lista clientes y el cliente a buscar. buscar cliente(lista clientes, cliente a buscar): Esta funci´ La funci´on debe mostrar toda la informaci´on que contenga el cliente a buscar. buscar transaccion enCliente(lista clientes, transaccion a buscar,cliente a buscar) : Esta fun-
ci´ on recibe la lista clientes, la transaccion a buscar y cliente a buscar. La funci´on debe mostrar el nombre, rut del cliente a buscar y adem´as todas las transacciones que sean del tipo transaccion a buscar de ese cliente. on recibe la lista clientes y la febuscar fechaTransaccion(lista clientes, fecha a buscar) : Esta funci´ cha a buscar. La funci´on debe mostrar todos los clientes que tengan transacciones en la fecha a buscar. En el caso que se est´e buscando y no se encuentren coincidencias, se debe mostrar el mensaje ”no existen coincidencias”.
59
class Cliente: de f __init__(self, _nombre ,_rut,_sexo ,_balance ,_trainicial ): s el f . n o mb r e = _ n om b re s el f . r ut = _ ru t s el f . s ex o = _ s ex o s e l f . b a l an c e = _ b a l an c e s el f . tr = [ ] (self.tr).append(_trainicial) de f a g r e g a r _t r a n s a c ci o n ( s e lf , n u e v a t r an s a c c i on ) : # R e ci b e l a t u pl a l i st a (self.tr).append(nuevatransaccion) de f verifica_balance(self): if self. balance >=0: r e t ur n T r ue r e t u rn F a l se de f actualiza_balance(self,monto): s e l f . b a l an c e = m o n to de f printCliente(self): print ( s e l f . n o m b r e +" , " + s e l f . r u t +" , "+ s e l f . s e x o +" ,") print ( s e l f . t r )
de f mostrar_menuprincipal(): a = in t ( input ( " S e l ec c io n e u na a c ci o n :\ n [ 1] C r ea r c l ie n te \ n [ 2] M o st r ar c l ie n te s \ n [ 3] B u sc a r c l i return a de f mostrar_menubusqueda(): a = in t ( input ( " I n g re s e e l t ip o d e b u sq u ed a : \ n [1 ] P or n o mb r e c l ie n te \ n [ 2] P or n o mb r e d e c l ie n te return a de f buscar_c liente( lista_clientes ,cliente _a_buscar ): fo r c l i en t e i n l i s t a _ cl i e n t e s : # R e ci b e n o mb r e d e c l ie n te if c l i en t e . n o m b r e = = c l i e n t e _a _ b u s c ar : return cliente return None de f r e a l i z a r _ b u s q u ed a ( n u m , l i s t a _ cl i e n t e s ) : c ou nt = 1 mat ched = False if num==1: n o mb r e = input (" I n g re s e n o mb r e c l ie n te : ") mi cliente = bu scar_c liente ( lista _cli ente s , no mbr e ) if micliente!=None: mat ched = True print ( " [" + st r ( c o u n t ) +" ] " ,end= " ") micliente . p rintCliente () count+=1 elif num==2:
60
n o mb r e = input (" I n g re s e n o mb r e c l ie n te : ") tx = input ( " I n gr e se t i po d e t r an s a cc i on : ") match ed = b usc ar _tr an sac ci on_ enC li ent e ( lis ta_c lien tes , tx , nom bre )
elif num==3: f e ch a = input ( " I n gr e se f ec h a : " ) match ed = b usc ar_ fec haT ran sac cio n ( li sta_c lien tes , fe ch a )
i f n ot ( m a t c h e d ) an d num!=4: print ( " N o e x i s te n c o i n c i de n c i a s ") print ( " ")
de f m o s t r a r _c l i e n t e s ( l i s t a _ cl i e n t e s ) : c ou nt = 1 fo r c l i en t e i n l i s t a _ cl i e n t e s : print ( "[ "+ st r (count)+ " ] " ,end= "" ) cliente.printCliente() count+=1 de f buscar_fechaT ransaccion (lista_clientes ,fecha_a_bus car): a ux = [] mat ched = False c ou nt = 1 i m pr i mi r = False fo r c l i en t e i n l i s t a _ cl i e n t e s : fo r t x i n c l ie n te . t r : if f e c h a_ a _ b u s ca r i n t x [ 1 ] : match ed = True i m pr i mi r = True aux.append(tx) if imprimir: print ( " [" + st r ( c o u n t ) +" ] " + c l i e n t e . n o m b r e +" , " + c l i e n t e . r u t +" , "+ c l i e n t e . s e x o +" ," ) print ( a u x ) count+=1 au x = [] i m pr i mi r = False return matched de f buscar_transacci on_enCliente (lista_clientes ,transaccion_a_buscar ,cliente _a_buscar ): a ux = [] i m pr i mi r = False mat ched = False c ou nt = 1 fo r c l i en t e i n l i s t a _ cl i e n t e s : if c l i en t e . n o m b r e = = c l i e n t e _a _ b u s c ar : fo r t r an i n c l ie n te . t r : if t r a n s a c ci o n _ a _ b u sc a r i n t r a n [ 0 ]:
61
mat ched = True i m pr i mi r = True aux.append(tran) if imprimir: print ( " [" + st r ( c o u n t ) +" ] " + c l i e n t e . n o m b r e +" , " + c l i e n t e . r u t +" , "+ c l i e n t e . s e x o +" ," ) print ( a u x ) count+=1 au x = [] i m pr i mi r = False return matched de f crea_clientes(): n om = input ( " I n gr e se n o mb r e d el c l ie n te : ") r ut = input ( " I n gr e se R UT d el c l ie n te : ") g = input ( " I n gr e se g e ne r o d el c l ie n te : ") b = in t ( input ( " I n g re s e b a la n ce : " )) tx = input (" I n g re s e t r an s ac c io n : " ) t x2 = t x . s pl i t (" ," ) b al = ( t x2 [ 3 ] ). r e p la c e (" " ," ") b al 2 = in t ( b a l ) t u p la = ( t x 2 [ 0 ] , t x 2 [ 1] , t x 2 [ 2 ] , b a l 2 ) c l = C l i e nt e ( n o m , r ut , g , b , t u p l a ) return cl de f agregar_tx(lista_clientes): print ( " S e l ec c io n e c l ie n te : " ) m ostra r_cl iente s ( list a_clie ntes ) n3 = in t ( input () ) c li = c l ie n te s [ n3 - 1 ] t ip o = input (" I n g re s e t i po d e t r an s ac c io n : ") f ec = input ( " I n gr e se f e ch a d e t r an s ac c io n : ") de = input (" I n g re s e d e sc r ip c c io n : ") m = in t ( input ( " I n g re s e m o nt o d e l a t r an s ac c i on : " )) if t i po = = " G i r o " or t i po = = " C o m p r a ": a ux = c li . b a l an c e c l i . a c t u a l iz a _ b a l a nc e ( a u x - m ) i f n ot ( c l i . v e r i f i c a _ b a l a n c e ( ) ) : print ( " N o p o se e s u fi c ie n te s al d o ") cli.actualiza_balance(aux) else : a = ( t ip o , f ec , d e , m ) cli.agregar_transaccion(a) print ( " S e h a a g re g ad o u na t r an s ac c io n a l c l ie n te "+ st r ( c l i . n o m b r e ) ) print ( c l i . t r ) print ( " ") else : a ux = c li . b a l an c e c l i . a c t u a l iz a _ b a l a nc e ( a u x + m ) a = ( t ip o , f ec , d e , m ) cli.agregar_transaccion(a) print ( " S e h a a g re g ad o u na t r an s ac c io n a l c l ie n te "+ st r ( c l i . n o m b r e ) ) print ( c l i . t r ) print ( "" )
62
#Programa print ( " B i e nv e ni d o a l S i st e ma d e B a nc o d e l a P l az a ") c l ie n te s = [ ] n u m e ro = m o s t r a r _m e n u p r i n ci p a l ( ) while numero!=5: if n u me r o = = 1 : c l = c r ea _ c li e nt e s ( ) clientes.append(cl) print ( " E l c l ie n te " + c l . n o m b r e +" f ue i n gr e sa d o c o rr e ct a m en t e ") print ( "" ) elif n u me r o = = 2 : mos trar_ clien tes ( client es ) print ( "" ) elif n u me r o = = 3 : n 2 = m o s t r a r _m e n u b u s q ue d a ( ) realizar_busqueda(n2,clientes) print ( "" ) elif n u me r o = = 4 : agregar_tx(clientes) n u m er o = m o s t r a r _ me n u p r i n ci p a l ( )
print ( " G ra ci as p or e le gi r e l S is te ma d e B an co d e l a P la za ! ")
63
12.3.
Algebraco
Algebraco1 es una aplicaci´on que sirve para manipular expresiones algebraicas. Internamente, Algebraco representa las expresiones aritm´eticas como: un n´ımero entero, o una lista de tres elementos, donde tanto el primer como el segundo elemento son expresiones, y el tercer elemento es un operador. Los operadores permitidos son los strings “+” , “-” , “*” y “/”. As´ı, 4, [1,[3,4,‘‘+’’],‘‘-’’] y [[5,5,‘‘/’’],[2,1,‘‘-’’],‘‘+’’] son expresiones permitidas en Algebraco que corresponden a 4, (1-(3+4)) y ((5/5) + (2-1)) respectivamente. 1. Escribe una funci´on evalua, que tome como argumento una expresi´on de Algebraco y retorne el n´umero al cual esta expresi´on es igual. Por ejemplo, evalua(4) debe retornar 4, evalua([1,[3,4,‘+’],‘-’]) debe retornar -6, evalua([[11,7,‘-’],[4,3,‘+’],‘*’]) debe retornar 28. Ayuda: Para saber si la variable a es un int, puedes preguntar if type(a) == int. 2. Informalmente, las subexpresiones de una expresi´on E son partes de E que al mismo tiempo son expresiones. Por ejemplo, si E = [1,[2,3,‘‘-’’],‘‘+’’], las subexpresiones de E son [1,[2,3,‘‘-’’],‘‘+’’], 1, [2,3,‘‘-’’], on, E es siempre una subexpresi´on de E. 2, y 3 . Por definici´ Escribe una funci´on cuenta que reciba una expresi´on y un n´umero, tal que cuenta(exp,n) retorne el n´ umero de subexpresiones de exp que, al evaluarse, tienen el valor n. Por ejemplo, cuenta([1,1,‘‘+’’],1) retorna 2 porque hay dos subexpresiones de [1,1,‘‘+’’], en particular 1 y 1, que son iguales a 1. # F u nc i on r e cu r si v a q ue e v al u a u na e x pr e si o n . de f evaluate(exp): if type(exp)== in t : return ex p else : if e xp [ 2 ] = = ’ + ’: return e v a l u at e ( e x p [ 0 ] ) + e v a l u at e ( e x p [ 1 ] ) elif e xp [ 2 ] = = ’ - ’: return e v a l u at e ( e x p [ 0 ] ) - e v a l u at e ( e x p [ 1 ] ) elif e xp [ 2 ] = = ’ * ’: return e v a l u at e ( e x p [ 0 ] ) * e v a l u at e ( e x p [ 1 ] ) elif e xp [ 2 ] = = ’ / ’: return e v a l u at e ( e x p [ 0 ] ) / e v a l u at e ( e x p [ 1 ] ) # F u nc i on r e cu r si v a q ue r e to r na u na l i st a c on t o da s l as s u b ex p re s i on e s . de f subexp(exp,l): l.append(exp) if t y pe ( e x p [ 0 ] ) = = in t : l.append(exp[0]) else : subexp(exp[0],l) if t y pe ( e x p [ 1 ] ) = = in t : l.append(exp[1]) else : subexp(exp[1],l) 1
Examen 2013-2
64