Você está na página 1de 9

ESCUELA SUPERIOR POLITÉCNICA DEL LITORAL

FACULTAD DE INGENIERIA EN ELECTRICIDAD Y COMPUTACION


PRACTICA AUTÓNOMA UNIDAD 7 – COLECCIONES

Listas y Tuplas

Se indexan por números consecutivos


ordenados que comienzan desde cero

0,1,...,n-1

Diccionarios
Los diccionarios son colecciones de datos que permiten definir y acceder a los componentes
mediante una clave. Cada componente de un diccionario es un par {clave: valor}.

Los diccionarios se indexan con claves, No se indexan mediante un rango numérico, como listas o
tuplas.

Se indexan por números consecutivos


ordenados que comienzan desde cero

0,1,...,n-1

Los componentes de un diccionario no están en


un orden específico, se indexan por la clave que
puede ser de cualquier tipo (inmutable)

Operaciones con Diccionarios


- Si se desea acceder a un valor del diccionario por medio de una clave, basta con colocar la clave
entre corchetes luego del nombre del diccionario:
get devuelve el valor de una clave específica, si la clave no existe devuelve None :

Pregunta 1 ¿Cómo puedo saber cuál es la materia con clave 215?


Pregunta 2 ¿Qué valor devuelve x [318] ?
Pregunta 3 ¿Qué valor devuelve x.get(318) ?

Se puede usar el operador in con diccionarios tal y como se lo hace con listas y tuplas para verificar
que una clave se encuentra en el diccionario.

in NO indica si un valor se encuentra en el diccionario (solamente busca en


las claves), para eso se debe recorrer el diccionario o pedir los valores del
diccionario (lo cual se explica más adelante).

No se pueden modificar las claves, pero si los valores asociados a las mismas.

Para agregar un nuevo par clave-valor se escribe la clave entre corchetes y se iguala al valor

Si se tiene el siguiente diccionario que representa la cantidad de estudiantes por paralelo:


paralelos = {'Paralelo01': 30, 'Paralelo14': 26, 'Paralelo08': 29, 'Paralelo02': 30}

Pregunta 4: Qué instrucción(es) debo utilizar para aumentar un estudiante al paralelo 14?
Pregunta 5: Cómo puedo saber cuántos estudiantes hay en el paralelo 20?
Pregunta 6: Cuál es el resultado de la instrucción print(paralelos['paralelo08'] ?
Pregunta 7: Qué instrucción(es) debo utilizar para crear un nuevo paralelo (Paralelo 40) sin ningún
estudiante?

Para eliminar un par clave-valor se utiliza la función del


Si se trata de eliminar un par clave-valor que no existe en el diccionario, se
produce un error. Para eliminar se recomienda primero verificar que el par
existe con in

Para obtener los datos de un diccionario se puede utilizar keys, values e items.
keys retorna las claves y values devuelve los valores, ambos son retornados en una estructura
específica de los diccionarios:

Si se desea trabajar con listas, se debe realizar el casting respectivo:

items retorna todos los datos del diccionario, donde cada elemento corresponde a una tupla (clave,
valor) :

Una vez obtenidos los datos de los diccionarios, se los puede recorrer con un lazo. Por ejemplo:

Pregunta 8: Cuál es la salida por pantalla del ejemplo anterior?

Se puede recorrer directamente un diccionario mediante un lazo (Recorrido 3 en


el ejemplo anterior). En este caso, los valores sobre los que se itera son las claves
del diccionario.

Taller

Si ya conoce el uso de archivos en Python seguir la opción (a) del taller, caso
contrario seguir la opción (b).
Determinar el vencedor en una batalla pokemon. Cada pokemon tiene un ID, nombre, tipo, y poder
de ataque.

En una batalla, el tipo de cada pokemon influye en su fuerza de ataque dependiendo del tipo del
adversario. Así, el ataque se puede duplicar (x2), demediar (x0.5) o anular (x0).

a)
El archivo pokedex.txt contiene el listado de los pokemones con sus datos:
ID|POKEMON|TYPE|ATK

El archivo tiposPokemon.txt contiene un listado de cada tipo y su efecto sobre otros tipos
de pokemones:
TYPE|SUPER - 2X|HALF - 0.5X|ZERO - 0X, donde SUPER, HALF y ZERO es el listado de
tipos que afectan el ataque, separados por '/'

b)
La lista pokedex contiene el listado de los pokemones con sus datos:
ID|POKEMON|TYPE|ATK
pokedex =['001|Bulbasaur|Grass|49\n', '002|Ivysaur|Grass|62\n', ...
, '721|Volcanion|Fire|110\n']

La lista tiposPokemon contiene un listado de cada tipo y su efecto sobre otros tipos de
pokemones:
TYPE|SUPER - 2X|HALF - 0.5X|ZERO - 0X, donde SUPER, HALF y ZERO es el listado de
tipos que afectan el ataque, separados por '/'

tiposPokemon =['DARK TYPE|GHOST/PSYCHIC|DARK/FIGHTING/STEEL|\n',


'DRAGON TYPE|DRAGON|STEEL|FAIRY\n', …,
'NORMAL TYPE||ROCK/STEEL|GHOST\n']

Por ejemplo: 'DARK TYPE|GHOST/PSYCHIC|DARK/FIGHTING/STEEL|\n' implica que un pokemon


tipo DARK duplica su ataque contra pokemones de tipo GHOST y PSYCHIC, mientras que demedia
su ataque contra pokemones de tipo DARK, FIGHTING y STEEL. Finalmente, sus ataques no se
anulan contra ningún tipo de pokemon.

Definir las siguientes funciones:

a)
cargarPokedex(nombreArchivo), que retorna un diccionario con los datos de los
pokemones:
{ ID:[POKEMON,TYPE,ATK]}
Por ejemplo:
{1:['Bulbasaur', 'Grass',49], …,8:['Wartortle', 'Water',63]}

cargarTipos(nombreArchivo), que retorna un diccionario con los tipos de pokemones


{TYPE:[[SUPER],[HALF],[ZERO]}
Por ejemplo:
{'DARK': [['GHOST', 'PSYCHIC'], ['DARK', 'FIGHTING', 'STEEL'], ['']], …,
'NORMAL': [[''], ['ROCK', 'STEEL'], ['GHOST']]}

b)
cargarPokedex(pokedexLista), que retorna un diccionario con los datos de los
pokemones:
{ ID:[POKEMON,TYPE,ATK]}
Por ejemplo:
{1:['Bulbasaur', 'Grass',49], …,8:['Wartortle', 'Water',63]}

cargarTipos(tiposPokemonLista), que retorna un diccionario con los tipos de pokemones


{TYPE:[[SUPER],[HALF],[ZERO]}
Por ejemplo:
{'DARK': [['GHOST', 'PSYCHIC'], ['DARK', 'FIGHTING', 'STEEL'], ['']], …,
'NORMAL': [[''], ['ROCK', 'STEEL'], ['GHOST']]}

seleccionarPokemones(pokedex), que recibe un diccionario como el creado por la función


cargarPokedex y retorna 2 códigos diferentes de pokemones seleccionados al azar.

batallaPokemon(IDpokemon1,IDpokemon2,pokedex,dicTiposPokemon), que determina el


vencedor de una batalla pokemon, según la siguiente regla:

El poder de ataque de cada pokemon se multiplica por el factor determinado por las listas SUPER,
HALF y ZERO (si el tipo del oponente se encuentra en dichas listas) y el vencedor es el de mayor
ataque resultante. Por ejemplo:

batallaPokemon(1,8,pokedex,dicTiposPokemon)

1:[Bulbasaur,Grass,49]
'GRASS': [['GROUND', 'ROCK', 'WATER'], ['BUG', 'DRAGON', 'FIRE', 'FLYING', 'GRASS',
'POISON', 'STEEL'], ['']]
Water (tipo del oponente) se encuentra en la lista SUPER, por lo tanto el ataque de
Bulbasaur se multiplica por 2.
Ataque = 49 * 2 = 98

8:[Wartortle,Water,63]
'WATER': [['FIRE', 'GROUND', 'ROCK'], ['DRAGON', 'GRASS', 'WATER'], ['']]
Grass (tipo del oponente) se encuentra en la lista HALF, por lo tanto el ataque de Bulbasaur
se multiplica por 0.5
Ataque = 63 * 0.5 = 31.5

98 >31.5 -> Vencedor: 1 – Bulbasaur. (La función retorna el ID del vencedor o 0 si es empate)

El programa principal debe cargar los diccionarios requeridos de las listas (o de los archivos
'tiposPokemon.txt' y 'pokedex.txt'), luego debe seleccionar 2 pokemones al azar y mostrar en pantalla
los siguientes datos de la batalla:

-- Batalla Pokemon --
Equipo Azul: ID1 - NOMBRE_POKEMON1 de tipo: TIPO1 y ataque: ATAQUE1
Equipo Rojo: ID2 - NOMBRE_POKEMON2 de tipo: TIPO2 y ataque: ATAQUE2
Vencedor: NOMBRE_POKEMON (o EMPATE)
cargarPokedex

a)
La función cargarPokedex recibe como parámetro el nombre del archivo que contiene los
datos de pokemones. Como sabemos cuál es el nombre por defecto del archivo, se lo ha
designado como parámetro clave.

def cargarPokedex(nombreArchivo = 'pokedex.txt'):

Dentro de la función se procede a abrir el archivo en modo lectura y se lee la primera línea, la
cual contiene la cabecera y no se utiliza en este caso particular.

archivo = open(nombreArchivo, 'r')


archivo.readline()

b)
Se definen las funciones getPokedex y getTiposPokemon, que retornan las listas por defecto.

def getPokedex():
return ['001|Bulbasaur|Grass|49\n', '002|Ivysaur|Grass|62\n', ... ]

def getTiposPokemon():
return ['DRAGON TYPE|DRAGON|STEEL|FAIRY\n', ... ]

La función cargarPokedex recibe como parámetro el nombre la lista que contiene los datos
de pokemones. Como podemos obtener la lista de defecto con getPokedex(), se lo ha
designado como parámetro clave.

def cargarPokedex(lista = getPokedex()):

Para cargar los datos en el diccionario, primero se crea un diccionario vacío.

diccionario = { }

Luego se procede a leer los datos del archivo (o la lista), línea por línea, por medio de un lazo for.
En cada iteración se elimina el caracter correspondiente al fin de línea por medio de strip (el valor por
defecto es ‘\n’) y se convierte la línea string a una lista, cuyos elementos van a ser definidos por el
limitante '|'. Por ejemplo, la línea '001|Bulbasaur|Grass|49\n' pasa a ser la lista
['001','Bulbasaur','Grass','49'], almacenada en la variable datos. Como el ataque es un tipo numérico
se procede a realizar el casting respectivo.

for linea in archivo:


datos = linea.strip().split('|')
datos[3] = int(datos[3])

Luego, se almacenan los datos en el diccionario. La clave debe ser un valor numérico
correspondiente al código (datos[0]), mientras que el valor es una lista con el nombre, tipo y ataque
(datos[1], datos[2], datos[3]). Consecuentemente, se asignan los datos al diccionario realizando un
casting para la clave y el slicing respectivo para el valor

diccionario [ int(datos[0]) ] = datos[1: ]

Una vez concluido el lazo, se procede a cerrar el archivo y retornar el diccionario.

archivo.close()
return diccionario

cargarTipos

La función cargarTipos tiene la misma lógica para leer los datos de la fuente (archivo o lista), la
diferencia se da al llenar el diccionario dentro del lazo for.

En cada iteración se elimina el caracter correspondiente al fin de línea, se convierte la línea string a
una lista y cada elemento de la lista se la almacena en una variable (tipo, doble, mitad, cero).

for linea in archivo:


tipo,doble,mitad,cero = linea.strip().split('|')

Por ejemplo, los datos de la línea 'DARK TYPE|GHOST/PSYCHIC|DARK/FIGHTING/STEEL|\n' se


almacenan en las siguientes variables:

tipo  'DARK TYPE'


doble  'GHOST/PSYCHIC'
mitad  'DARK/FIGHTING/STEEL'
cero  ''

De la variable tipo, solamente nos interesa lo que está por delante de ' TYPE' por lo que se realiza el
slicing correspondiente (se descartan los 5 últimos caracteres).

tipo = tipo[ :-5]

Luego, se almacenan los datos en el diccionario. La clave debe ser el tipo, mientras que el valor es
una lista de las listas doble, mitad y cero. Consecuentemente, se crean listas a partir de las variables
de tipo string, por medio de split('/') y cada una de estas listas pasa a ser un elemento de la lista que
se asigna como valor del diccionario.

diccionario[ tipo ] = [ doble.split('/'), mitad.split('/'), cero.split('/') ]

Una vez concluido el lazo, se procede a cerrar el archivo y retornar el diccionario.

archivo.close()
return diccionario

seleccionarPokemones

La función seleccionarPokemones retorna una muestra de 2 elementos seleccionados al azar de las


claves del diccionario que recibe como parámetro. Para esto se utiliza la función sample de la librería
random. El primer parámetro de sample indica la colección de donde se extraen las muestras y el
segundo parámetro indica el número de muestras a obtener. Para el primer parámetro se obtienen
todas las claves por medio de .keys() y el segundo parámetro es 2 (debido a que se desean 2
claves).
def seleccionarPokemones(pokedex):
ID1, ID2 = random.sample(pokedex.keys(), 2)
return ID1, ID2

batallaPokemon

En la función batallaPokemon, primero se determina cual es el tipo y el ataque de cada pokemon.


Para esto se extrae la lista corespondiente al ID de cada pokemon en el diccionario pokedex { ID:
[POKEMON,TYPE,ATK] }. Dentro de esta lista se obtiene el tipo, que se encuentra en el índice 1; y el
ataque, que se encuentra en el índice 2. Debido a que el tipo se almacena en mayúscula en
dicTiposPokemon, se utiliza upper() para que la variables tipo1 y tipo2 también estén en mayúsculas.

def batallaPokemon(IDpokemon1,IDpokemon2,pokedex,dicTiposPokemon):
tipo1 = pokedex[IDpokemon1][1].upper()
tipo2 = pokedex[IDpokemon2][1].upper()
ataque1 = pokedex[IDpokemon1][2]
ataque2 = pokedex[IDpokemon2][2]

Luego, se determina si el tipo de un pokemon se encuentra en alguna de las listas (doble, mitad o
cero) que son afectadas por el tipo del pokemon oponente. De ser ese el caso, se procede a
recalcular el ataque del pokemon oponente

if tipo2 in dicTiposPokemon[tipo1][0]: #doble


ataque1 *= 2
elif tipo2 in dicTiposPokemon[tipo1][1]: #mitad
ataque1 *= 0.5
elif tipo2 in dicTiposPokemon[tipo1][2]: #cero
ataque1 *= 0

if tipo1 in dicTiposPokemon[tipo2][0]: #doble


ataque2 *= 2
elif tipo1 in dicTiposPokemon[tipo2][1]: #mitad
ataque2 *= 0.5
elif tipo1 in dicTiposPokemon[tipo2][2]: #cero
ataque2 *= 0

Finalmente, se retorna el ID del pokemon con mayor ataque, si ambos ataques son iguales se retorna
0.
if ataque1 > ataque2:
return IDpokemon1
if ataque2 > ataque1:
return IDpokemon2
return 0

Programa Principal

Previo a iniciar el programa principal, se organizan todas las funciones en módulos, según su
afinidad.
El programa principal (autonomo7.py) importa los módulos requeridos y hace uso de las funciones
previamente declaradas

import pokemon.batalla as batalla


import pokemon.cargarArchivos as arch
import pokemon.cargarListas as lista

#cargar diccionario desde archivos


pokedex=arch.cargarPokedex()
dicTipos=arch.cargarTipos()

'''
#cargar diccionario desde listas
pokedex=lista.cargarPokedex()
dicTipos=lista.cargarTipos()
'''

pokemon1, pokemon2 = batalla.seleccionarPokemones(pokedex)


print('-- Batalla Pokemon --')
print('Equipo azul: {0:10} de tipo: {1:8} y ataque:
{2}'.format(pokedex[pokemon1][0],pokedex[pokemon1][1],pokedex[pokemon1][2]))
print('Equipo rojo: {0:10} de tipo: {1:8} y ataque:
{2}'.format(pokedex[pokemon2][0],pokedex[pokemon2][1],pokedex[pokemon2][2]))
vencedorID = batalla.batallaPokemon(pokemon1,pokemon2,pokedex,dicTipos)
if vencedorID == 0:
print('Empate')
else:
print('Vencedor:',pokedex[vencedorID][0] )

Você também pode gostar