In [1]:
"""
IPython Notebook v4.0 para python 2.7
Librerías adicionales: Ninguna.
Contenido bajo licencia CC-BY 4.0. Código bajo licencia MIT. (c) Sebastian Flores.
"""

# Configuracion para recargar módulos y librerías 
%reload_ext autoreload
%autoreload 2

from IPython.core.display import HTML

HTML(open("style/iwi131.css", "r").read())


Out[1]:






IWI131

Programación de Computadores

Sebastián Flores

http://progra.usm.cl/

https://www.github.com/usantamaria/iwi131


In [1]:
m = 'Edkhy`°nmtdun '
s = ""
for c in m:
    s += chr(ord(c)+1)
print s


Feliz año nuevo!

In [14]:
m = 'Mensaje Secreto'
s = ""
for c in m:
    s += chr(ord(c)-1)
print s


Ldmr`idRdbqdsn

Fechas

  • Miércoles 6 Enero, 8:00. Actividad 5.
  • Viernes 8 Enero, 15:40. Certamen 3.
  • Lunes 18 Enero, 8:00. Certamen Recuperativo.

Problemas solicitados por correo

  • Telégrafo.

1. Telégrafo

Dado un mensaje, se debe calcular su costo para enviarlo por telégrafo. Para esto se sabe que cada letra cuesta \$10, los caracteres especiales que no sean letras cuestan \$30 y los dígitos tienen un valor de \$20 cada uno. Los espacios no tienen valor.

Su mensaje debe ser un string, y las letras del castellano (ñ, á, é, í, ó, ú) se consideran caracteres especiales.

Mensaje: Feliz Aniversario!
Su mensaje cuesta $190

In [2]:
def costo_mensaje(msg):
    return 0

msg = raw_input("Mensaje: ")
while len(msg)!=0:
    costo = costo_mensaje(msg)
    print "Su mensaje cuesta ${0}".format(costo)
    msg = raw_input("Mensaje: ")


Mensaje: Hla
Su mensaje cuesta $0
Mensaje: Hmm
Su mensaje cuesta $0
Mensaje: Hmmm
Su mensaje cuesta $0
Mensaje: 

In [8]:
def costo_mensaje(msg):
    letras_sin_valor = " "
    letras_normales = "abcdefghijklmnopqrstuvwxyz"
    digitos = "0123456789"
    costo = 0
    for letra in msg.lower():
        if letra in letras_sin_valor:
            costo += 0
        elif letra in letras_normales:
            costo += 10
        elif letra in digitos:
            costo += 20
        else:
            costo += 30
    return costo

msg = raw_input("Mensaje: ")
while len(msg)!=0:
    costo = costo_mensaje(msg)
    print "Su mensaje cuesta ${0}".format(costo)
    msg = raw_input("Mensaje: ")


Mensaje: feliz ANIVERSARIO!
Su mensaje cuesta $190
Mensaje: 

Pregunta 2, Certamen 3, Primer Semestre, 2014.

Los registros de un sismo se guardan en un archivo con la siguiente estructura (siempre en el mismo orden):

{mag:float,place:string,dept:float,
tsunami:integer,date:string,time:string}

Considere como ejemplo el archivo registro.geojson:

{mag:7.0,place:Iquique,dept:10.0,
 tsunami:1,date:2014-03-15,time:15:44:13}
{mag:5.8,place:Salvador,dept:23.0,
 tsunami:0,date:2014-03-17,time:06:11:08}
{mag:3.1,place:California,dept:22.0,
 tsunami:0,date:2014-03-17,time:17:55:33}
{mag:2.5,place:Quilpue,dept:10.0,
 tsunami:0,date:2014-03-23,time:02:41:09}
{mag:4.6,place:Iquique,dept:98.0,
 tsunami:0,date:2014-03-28,time:20:34:22}

(a) Leer una linea

Desarrolle la función interpretar_geojson(linea) que reciba como parámetro un string con la misma estructura que tienen las lineas del archivo geojson y retorne un diccionario con los datos formateados como muestra el ejemplo.

>>> interpretar_geojson('{mag:5.8,place:Salvador,dept:23.0,tsunami:0, date:2014-03-17,time:06:11:08}')
{'mag': 5.8, 
 'place': 'Salvador', 
 'dept': 23.0, 
 'tsunami': 0, 
 'date': (2014, 3, 17), 
 'time': '06:11:08'}

In [9]:
def interpretar_geojson(linea):
    d = {}
    return d
    
    
print interpretar_geojson('{mag:5.8,place:Salvador,dept:23.0,tsunami:0, date:2014-03-17,time:06:11:08}')


{}

In [9]:
def interpretar_geojson(linea):
    d = {}
    # sacar caracteres innecesarios: {,} y \n
    # separar datos con split
    # procesar datos
    # regresar el diccionario
    return d    
    
print interpretar_geojson('{mag:5.8,place:Salvador,dept:23.0,tsunami:0, date:2014-03-17,time:06:11:08}')


{}

In [46]:
def interpretar_geojson(linea):
    d = {}
    # sacar caracteres innecesarios: {,}. OBS: No trae \n
    linea = linea[1:-1]
    # separar datos con split
    datos = linea.split(",")
    # procesar datos
    mag = datos[0].split(":")[-1]
    d["mag"] = float(mag)
    place = datos[1].split(":")[-1]
    d["place"] = place
    dept = datos[2].split(":")[-1]
    d["dept"] = float(dept)
    tsunami = datos[3].split(":")[-1]
    d["tsunami"] = int(tsunami)
    date = datos[4].split(":")[-1]
    yyyy,mm,dd = date.split("-")
    d["date"] = (int(yyyy),int(mm),int(dd))
    time = datos[5].replace("time:","") # Ojo!!!
    d["time"] = time
    # regresar el diccionario
    return d    
    
print interpretar_geojson('{mag:5.8,place:Salvador,dept:23.0,tsunami:0, date:2014-03-17,time:06:11:08}')


{'dept': 23.0, 'tsunami': 0, 'place': 'Salvador', 'mag': 5.8, 'time': '06:11:08', 'date': (2014, 3, 17)}

(b) Mayor Sismo

Desarrolle la función mayor_sismo(nombre_archivo) que reciba como parámetro el nombre del archivo y retorne una tupla con: la magnitud, lugar, y fecha (también como tupla) del sismo con mayor magnitud.

>>> mayor_sismo("registro.geojson")
(7.0, 'Iquique', (2014, 3, 15))

In [10]:
def mayor_sismo(nombre_archivo):
    return ()

print mayor_sismo("data/registro.geojson")


()

In [19]:
def mayor_sismo(nombre_archivo):
    # Abrir archivo
    # Inicializar mayor magnitud
    # Recorrer lineas del archivo
    # Procesar cada linea, cuidado con \n
    # Actualizar el mayor
    # Cerrar archivo
    return ()

print mayor_sismo("data/registro.geojson")


()

In [23]:
def mayor_sismo(nombre_archivo):
    # Abrir archivo
    archivo = open(nombre_archivo)
    # Inicializar mayor magnitud
    mayor_mag = -float("inf")
    mayor_tupla = ()
    # Recorrer lineas del archivo
    for linea in archivo:
        # Procesar cada linea, cuidado con \n
        d = interpretar_geojson(linea.strip())
        # Actualizar el mayor
        if d["mag"] > mayor_mag:
            mayor_mag = d["mag"]
            mayor_tupla = (d["mag"], d["place"], d["date"])
    # Cerrar archivo
    archivo.close()
    return mayor_tupla

print mayor_sismo("data/registro.geojson")


(7.0, 'Iquique', (2014, 3, 15))

(c) Mostrar registro

Desarrolle la función mostrar_registro(nombre_archivo, mag) que reciba como parámetro el nombre del archivo y un numero real. La función debe mostrar por pantalla los registros donde la magnitud es mayor o igual al segundo parámetro, en el formato:

PLACE <-> mag <-> dept <-> date-time

Guíese por el ejemplo. Además note que el lugar del epicentro esta en mayúscula. La función retorna nada.

>>> mostrar_registro("registro.geojson",4.4)
IQUIQUE <-> 7.0 <-> 10.0 <-> 2014-03-15-15:44:13
SALVADOR <-> 5.8 <-> 23.0 <-> 2014-03-17-06:11:08
IQUIQUE <-> 4.6 <-> 98.0 <-> 2014-03-28-20:34:22

In [11]:
def mostrar_registro(nombre_archivo, mag):
    return None

mostrar_registro("registro.geojson", 4.4)

In [44]:
def mostrar_registro(nombre_archivo, mag):
    # Abrir archivo
    # Recorrer lineas del archivo
    # Procesar cada linea
    # Si magnitud es >= a la indicada, imprimir en formato correcto
    # Cerrar archivo
    return None

mostrar_registro("registro.geojson", 4.4)

In [50]:
def mostrar_registro(nombre_archivo, mag):
    # Abrir archivo
    archivo = open(nombre_archivo)
    # Recorrer lineas del archivo
    for linea in archivo:
        # Procesar cada linea
        d = interpretar_geojson(linea.strip())
        # Si magnitud es >= a la indicada, imprimir en formato correcto
        if d["mag"]>=mag:
            date = "-".join(map(str,d["date"]))
            date_time = date + "-" + d["time"]
            datos = (d["place"].upper(), d["mag"], d["dept"], date_time)
            linea_imprimir = " <-> ".join( map(str, datos) ) 
            print linea_imprimir
    # Cerrar archivo
    archivo.close()
    return None

mostrar_registro("data/registro.geojson", 4.4)


IQUIQUE <-> 7.0 <-> 10.0 <-> 2014-3-15-15:44:13
SALVADOR <-> 5.8 <-> 23.0 <-> 2014-3-17-06:11:08
IQUIQUE <-> 4.6 <-> 98.0 <-> 2014-3-28-20:34:22

Pregunta 3, Certamen 3, Primer Semestre, 2014.

Se tienen los resultados de todos los partidos por grupos del mundial de fútbol 2014 en archivos de texto tales como los presentados a continuación.

Grupo1.txt

Brasil;3-Croacia;1
Mexico;1-Camerun;0
Brasil;0-Mexico;0
Camerun;0-Croacia;4
Camerun;1-Brasil;4
Croacia;1-Mexico;3

Grupo2.txt

Espania;1-Holanda;5
Chile;3-Australia;1
Australia;2-Holanda;3
Espania;0-Chile;3
Holanda;2-Chile;0
Australia;0-Espania;3

Tener en cuenta que se tienen los archivos Grupo1.txt hasta el Grupo8.txt.

(a) Obtener equipos

Desarrolle la función obtener_equipos(archivo), la cual recibe como parámetro el nombre de un archivo y retorna una lista con todos los equipos que se encuentran en el archivo.

>>> print obtener_equipos('Grupo2.txt')
['Chile', 'Australia', 'Espania', 'Holanda']

In [29]:
def obtener_equipos(archivo):
    return []

print obtener_equipos('data/Grupo2.txt')


[]

In [32]:
def obtener_equipos(archivo):
    # Abrir archivo
    # Inicializar conjunto
    # Leer cada linea del archivo
    # Agregar equipos a conjunto
    # Cerrar archivo
    # Convertir a lista y regresar
    return []

print obtener_equipos('data/Grupo2.txt')


[]

In [28]:
def obtener_equipos(archivo):
    # Abrir archivo
    arch = open(archivo)
    # Inicializar conjunto
    paises = set()
    # Leer cada linea del archivo
    for linea in arch:
        # Agregar equipos a conjunto
        p1,p2 = linea.split("-")
        pais,_ = p1.split(";")
        paises.add(pais)
        pais = p2.split(";")[0]
        paises.add(pais)
    # Cerrar archivo
    arch.close()
    # Convertir a lista y regresar
    return list(paises)

for i in range(1,9):
    print obtener_equipos('data/Grupo{0}.txt'.format(i))


['Camerun', 'Croacia', 'Brasil', 'Mexico']
['Espania', 'Holanda', 'Australia', 'Chile']
['Costa de Marfil', 'Japon', 'Colombia', 'Grecia']
['Inglaterra', 'Italia', 'Costa Rica', 'Uruguay']
['Francia', 'Suiza', 'Honduras', 'Ecuador']
['Argentina', 'Iran', 'Nigeria', 'Bosnia']
['Ghana', 'Portugal', 'Alemania', 'Estados Unidos']
['Rusia', 'Argelia', 'Corea del Sur', 'Belgica']

(b) Obtener clasificados

Desarrolle la función obtener_clasificados(archivo), la cual recibe como parámetro el nombre de un archivo y retorna una tupla con el nombre de los equipos que obtuvieron el primer y segundo lugar del grupo (debe ser en ese orden). En caso de que existan equipos con la misma cantidad de puntos considere la cantidad de goles anotados, si persistir el empate, retorne cualquiera. Considere que se otorgan 3 ptos por partido ganado, 1 por partido empatado y 0 por partido perdido.

>>> print obtener_clasificados('Grupo2.txt')
('Holanda', 'Chile')

In [34]:
def obtener_clasificados(archivo):
    return ()

print obtener_clasificados('Grupo2.txt')


()

In [30]:
def obtener_clasificados(archivo):
    # Calcular puntos
    # Calcular primer clasificado
    # Calcular segundo clasificado
    return ()

print obtener_clasificados('data/Grupo2.txt')


()

In [6]:
def obtener_clasificados(archivo):
    # Abrir archivo
    arch = open(archivo)
    # Inicializar conjunto
    puntajes = {}
    # Leer cada linea del archivo
    for linea in arch:
        pg1,pg2 = linea.strip().split("-")
        pais1,goles1 = pg1.split(";")
        pais2,goles2 = pg2.split(";")
        if pais1 not in puntajes:
            puntajes[pais1] = 0
        if pais2 not in puntajes:
            puntajes[pais2] = 0
        if goles1>goles2:
            puntajes[pais1] += 3
        elif goles1<goles2:
            puntajes[pais2] += 3
        else:
            puntajes[pais1] += 1
            puntajes[pais2] += 1
    # Cerrar archivo
    arch.close()
    # Calcular primer clasificado
    mayor_puntaje = -1
    primer_clasificado = ""
    for pais in puntajes:
        if puntajes[pais]>mayor_puntaje:
            primer_clasificado = pais
            mayor_puntaje = puntajes[pais]
    # Calcular segundo clasificado
    del puntajes[primer_clasificado]
    mayor_puntaje = -1
    segundo_clasificado = ""
    for pais in puntajes:
        if puntajes[pais]>mayor_puntaje:
            segundo_clasificado = pais
            mayor_puntaje = puntajes[pais]
    
    return (primer_clasificado, segundo_clasificado)

print obtener_clasificados('data/Grupo2.txt')


('Holanda', 'Chile')

Por supuesto, el método anterior es muy poco elegante. Podemos hacer algo mejor.


In [8]:
def obtener_puntajes(archivo):
    # Abrir archivo
    arch = open(archivo)
    # Inicializar conjunto
    puntajes = {}
    # Leer cada linea del archivo
    for linea in arch:
        pg1,pg2 = linea.strip().split("-")
        pais1,goles1 = pg1.split(";")
        pais2,goles2 = pg2.split(";")
        if pais1 not in puntajes:
            puntajes[pais1] = 0
        if pais2 not in puntajes:
            puntajes[pais2] = 0
        if goles1>goles2:
            puntajes[pais1] += 3
        elif goles1<goles2:
            puntajes[pais2] += 3
        else:
            puntajes[pais1] += 1
            puntajes[pais2] += 1
    # Cerrar archivo
    arch.close()
    return puntajes

¿Como podemos definir ahora la funcion (a), obtener_paises?


In [9]:
# Pregunta (a)
def obtener_paises(archivo):
    return obtener_puntajes(archivo).keys()

print obtener_paises('data/Grupo2.txt')


['Espania', 'Holanda', 'Australia', 'Chile']

¿Como podemos definir ahora la funcion (b), obtener_clasificados?


In [29]:
def obtener_clasificados(archivo, k=2):
    # Obtener el diccionario de puntajes
    puntajes = obtener_puntajes(archivo)
    # Crear una lista con puntajes primero
    lista= list()
    for pais in puntajes:
        lista.append((puntajes[pais], pais))
    # Ordenar la lista
    lista.sort()
    lista.reverse()
    # Regresar los primeros k
    primeros = list()
    for i in range(k):
        puntaje, pais = lista[i]
        primeros.append(pais)
    return tuple(primeros)

print obtener_clasificados('data/Grupo2.txt')


['Holanda', 'Chile']

O, aún mejor (pero más riesgoso en un certamen)...


In [55]:
def obtener_clasificados(archivo, k=2):
    # Obtener el diccionario de puntajes
    puntajes = obtener_puntajes(archivo)
    # Ordenar el dict
    primeros = sorted(puntajes, key=puntajes.get, reverse=True)
    return tuple(primeros[:k])

for i in range(1,9):
    print obtener_clasificados('data/Grupo{0}.txt'.format(i), 2)


('Brasil', 'Mexico')
('Holanda', 'Chile')
('Colombia', 'Grecia')
('Costa Rica', 'Uruguay')
('Francia', 'Suiza')
('Argentina', 'Nigeria')
('Alemania', 'Portugal')
('Belgica', 'Argelia')

(c) Partidos de Octavos de Final

Desarrolle la función partidos_octavos(), la cual no recibe parámetros. Esta función debe crear el archivo Partidos_octavos.txt el cual debe poner en cada línea del archivo los equipos que se enfrentarán en octavos de final. Los partidos se forman de la siguiente forma: el primero del grupo1 se enfrenta al segundo del grupo2, el primero del grupo2 se enfrenta al segundo del grupo1, lo mismo sucede para los grupos 3-4, grupos 5-6 y grupo 7-8.

>>> partidos_octavos()
>>>

Debería generar el archivo Partidos_octavos.txt con el siguiente contenido:

Brasil v/s Chile
Holanda v/s Mexico
Colombia v/s Uruguay
Costa Rica v/s Grecia
Francia v/s Nigeria
Argentina v/s Suiza
Alemania v/s Argelia
Belgica v/s EEUU

In [42]:
def partidos_octavos():
    # Abrir archivo para escribir lineas
    # Obtener clasificados para grupos 1 y 2
    # Escribibir pares cruzados
    # Obtener clasificados para grupos 3 y 4
    # Escribibir pares cruzados
    # Obtener clasificados para grupos 5 y 6
    # Escribibir pares cruzados
    # Obtener clasificados para grupos 7 y 8
    # Escribibir pares cruzados
    # Cerrar archivo
    return None

partidos_octavos()

In [42]:
def partidos_octavos():
    grupos = ((1,2),(3,4),(5,6),(7,8))
    archivo = open("data/Partidos_octavos.txt", "w")
    template = "{0} v/s {1}\n"
    pa1, pa2 = obtener_clasificados('data/Grupo1.txt')
    pb1, pb2 = obtener_clasificados('data/Grupo2.txt')
    archivo.write( template.format(pa1, pb2) )
    archivo.write( template.format(pb1, pa2) )
    pa1, pa2 = obtener_clasificados('data/Grupo3.txt')
    pb1, pb2 = obtener_clasificados('data/Grupo4.txt')
    archivo.write( template.format(pa1, pb2) )
    archivo.write( template.format(pb1, pa2) )
    pa1, pa2 = obtener_clasificados('data/Grupo5.txt')
    pb1, pb2 = obtener_clasificados('data/Grupo6.txt')
    archivo.write( template.format(pa1, pb2) )
    archivo.write( template.format(pb1, pa2) )
    pa1, pa2 = obtener_clasificados('data/Grupo7.txt')
    pb1, pb2 = obtener_clasificados('data/Grupo8.txt')
    archivo.write( template.format(pa1, pb2) )
    archivo.write( template.format(pb1, pa2) )
    archivo.close()
    return None

partidos_octavos()

In [56]:
def partidos_octavos():
    grupos = ((1,2),(3,4),(5,6),(7,8))
    archivo = open("data/Partidos_octavos.txt", "w")
    template = "{0} v/s {1}\n"
    for a,b in grupos:
        pa1, pa2 = obtener_clasificados('data/Grupo{0}.txt'.format(a))
        pb1, pb2 = obtener_clasificados('data/Grupo{0}.txt'.format(b))
        archivo.write( template.format(pa1, pb2) )
        archivo.write( template.format(pb1, pa2) )
    archivo.close()
    return None

partidos_octavos()

Sobre el certamen

Consejos para el certamen