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

Soluciones a Certamen 3, S1 2015, Casa Central

Pregunta 1 [30%]

Realice el ruteo del siguiente programa e indique qué es lo que imprime. Cada vez que el valor de una variable cambie, escríbalo en una nueva fila de la tabla. Si una variable es de tipo archivo, debe colocar cuando se abre y cierra el archivo indicando su nombre entre comillas simples ’ ’. Si hay algún archivo de escritura, se debe reflejar en el lo que el programa escriba. Importante: La tabla tiene suficientes filas.


In [2]:
a = open('f1.dat')
b = open('f2.dat', 'w')
c, j = 'ekil', -1
for x in a:
    p = list()
    for i in range(len(x)):
        if i %3 != 2:
            x.replace('e','x')
            b.write(x[i])
        else:
            ch = x.replace(x[i], c[j-(i/3)])
            p.append(ch[i])
        j = j - ((i+1)/3)
        print ''.join(p),
a.close()
b.close()


  l l l
---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
<ipython-input-2-e3d1641e4a57> in <module>()
      9             b.write(x[i])
     10         else:
---> 11             ch = x.replace(x[i], c[j-(i/3)])
     12             p.append(ch[i])
     13         j = j - ((i+1)/3)

IndexError: string index out of range

Pregunta 2 [35%]

La PyDI ha solicitado ayuda a los alumnos de IWI-131 para el desarrollo de algunas funciones que le permitan realizar búsquedas de comportamiento sospechoso de los ciudadanos de Pytonia. Para resolver esta tarea debes identificar a los posibles sospechosos para la PyDI, quienes siempre son menores de 41 años y publican en un medio distinto de Twitter. Para esto se revisan dos archivos, uno con la información de los ciudadanos y otro con las publicaciones de los usuarios. Ejemplos de estos archivos y su formato son publicaciones.txt y personas.txt.

En el archivo de publicaciones se tiene el rut del sospechoso y el medio en el cual fue publicado.

En el archivo de personas se encuentra el rut, la edad y 3 calificaciones (valores enteros) relacionadas al nivel de amenaza de sus ultimas 3 detenciones por la PyDI.

Por último se tiene un archivo por persona con los mensajes enviados (sin puntuación), el nombre de estos es el rut de cada quien (Ejemplo: el rut 15740994-7 tiene asociado el archivo 15740994-7.txt).

Pregunta 2 [35%]

personas.txt:

15740994-7,15,30-40-50
15735995-7,41,0-0-0
15756996-7,45,0-0-40
...

publicaciones.txt:

15756996-7:blogspot
15735995-7:twitter
15740994-7:facebook
...

15740994-7.txt:

La bomba esta en tu casa
Pedir mas polvora
...

Se le solicita a usted desarrollar las siguientes funciones:

Pregunta 2.a

Escriba la función sospechosos(personas, publicaciones) la cual reciba como parámetros dos archivos del tipo personas.txt y publicaciones.txt. Esta función debe retornar un conjunto con los rut de las personas que resulten sospechosas.

>>> sospechosos('personas.txt', 'publicaciones.txt')
set(['15740994-7'])

Estrategia de solución:

  • ¿Qué estructura tienen los datos de entrada?
  • ¿Qué estructura deben tener los datos de salida?
  • ¿Cómo proceso los inputs para generar el output deseado?

In [8]:
def sospechosos(nombre_archivo_personas, nombre_archivo_publicaciones):
    # Procesar archivo de personas
    archivo_personas = open(nombre_archivo_personas)
    edad_dict = {}
    for linea in archivo_personas:
        rut,edad_str,puntuacion_str = linea[:-1].split(",")
        edad = int(edad_str)
        edad_dict[rut] = edad
    archivo_personas.close()
    # Procesar archivo de publicaciones
    archivo_publicaciones = open(nombre_archivo_publicaciones)
    medio_dict = {}
    for linea in archivo_publicaciones:
        rut,medio = linea[:-1].split(":")
        medio_dict[rut] = medio
    archivo_publicaciones.close()
    # Cruzar los datos
    conjunto_sospechosos = set()
    for rut in edad_dict:
        if edad_dict[rut]<41 and medio_dict[rut]!="twitter":
            conjunto_sospechosos.add(rut)
    return conjunto_sospechosos
    
print sospechosos('data/personas.txt', 'data/publicaciones.txt')


set(['15740994-7'])

Pregunta 2.b

Escriba la función leer_mensajes(personas, publicaciones, claves), la cual recibe como parámetros 2 archivos del tipo personas.txt y publicaciones.txt, y una lista de palabras clave. Esta función debe retornar un diccionario cuya clave sea el rut de un sospechoso y el valor la cantidad de palabras claves que fueron encontradas en sus mensajes.

>>> claves = ['bomba', 'polvora', 'TNT']
>>> leer_mensajes('personas.txt', 'publicaciones.txt', claves)
{'15740994-7':2}

Estrategia de solución:

  • ¿Qué estructura tienen los datos de entrada?
  • ¿Qué estructura deben tener los datos de salida?
  • ¿Cómo proceso los inputs para generar el output deseado?

In [ ]:
def leer_mensajes(nombre_archivo_personas, nombre_archivo_publicaciones, claves):
    palabras_claves = {}
    for rut in sospechosos(nombre_archivo_personas, 
                           nombre_archivo_publicaciones):
        nombre_archivo_mensajes = "data/" + rut + ".txt"
        archivo_mensajes = open(nombre_archivo_mensajes)
        contador = 0
        for linea in archivo_mensajes:
            for palabra in linea[:-1].split(" "):
                if palabra in claves:
                    contador += 1
        palabras_claves[rut] = contador
    return palabras_claves
    
claves = ['bomba', 'polvora', 'TNT']
print leer_mensajes('data/personas.txt', 'data/publicaciones.txt', claves)
# OBS: ¿Como modificar si no se quiere contar palabras repetidas?

Pregunta 2.c

Escriba la función peligro(persona, publicaciones, claves), la cual recibe como parámetros 2 archivos del tipo personas.txt y publicaciones.txt, y una lista de palabras clave. Esta función retorna una lista con los rut de los sospechosos considerados peligrosos. Un sospechoso es considerado peligroso si posee un ranking de peligrosidad mayor o igual a 30 y además posee al menos 2 palabras claves en sus mensajes. Donde el ranking de peligrosidad se determina promediando las 3 ultimas calificaciones de detención.

>>> claves = ['bomba', 'polvora', 'TNT']
>>> peligro('personas.txt', 'publicaciones.txt', claves)
['15740994-7']

Estrategia de solución:

  • ¿Qué estructura tienen los datos de entrada?
  • ¿Qué estructura deben tener los datos de salida?
  • ¿Cómo proceso los inputs para generar el output deseado?

In [ ]:
def peligro(nombre_archivo_personas, nombre_archivo_publicaciones, claves):
    # Procesar archivo de personas
    archivo_personas = open(nombre_archivo_personas)
    ranking_dict = {}
    for linea in archivo_personas:
        rut,edad_str,puntuacion_str = linea[:-1].split(",")
        puntuaciones = map(float, puntuacion_str.split("-"))
        ranking = sum(puntuaciones[-3:])/3.0
        ranking_dict[rut] = ranking
    archivo_personas.close()
    # Obtener sospechosos
    conjunto_sospechosos = sospechosos(nombre_archivo_personas, 
                                       nombre_archivo_publicaciones)
    # Obtener peligrosos
    peligrosos = list()
    for rut in conjunto_sospechosos:
        if ranking_dict[rut]>=30:
            peligrosos.append(rut)
    return peligrosos

claves = ['bomba', 'polvora', 'TNT']
peligro('data/personas.txt', 'data/publicaciones.txt', claves)

Pregunta 3 [35%]

El proceso de postulación a las universidades es la fase en la cual miles de alumnos (tras rendir la PSU) esperan ser nominados en alguna carrera-universidad según sus preferencias, resultados y aptitudes. Para ello y esperando agilizar el proceso de postulación de la ciudad de Pytonia, se ha pedido a los alumnos de Programación realizar algunas funciones considerando los siguientes archivos:

estudiantes.txt:

Juan Perez;18298111-8
Maria Mercedes;17444222-1
Gustavo Lima;17543987-1
Javier Soto;18844222-7
Daniela Melendez;17999555-3
Alexis Vidal;16219345-6
...

postulaciones.txt:

18844222-7#UCH#Ing. Civil Electronica
16219345-6#UTFSM#Ing. Comercial
18298111-8#USACH#Periodismo
17444222-1#PUC#Enfermeria
17999555-3#UTFSM#Ing. Civil Industrial
17543987-1#PUC#Derecho
17999555-3#PUC#Ing. Civil Industrial
16219345-6#UTFSM#Piloto Comercial

En base a lo descrito anteriormente, se le solicita desarrollar las siguientes funciones:

Pregunta 3.a

Escriba la función universidades(nombre_archivo) que reciba como parámetro, un string con el nombre del archivo que contiene las postulaciones (como en el ejemplo el archivo postulaciones.txt). La función debe retornar un conjunto con todas las universidades que aparecen en el archivo postulaciones.

>>> universidades("postulaciones.txt")
set(['UCH','UTFSM','USACH','PUC'])

Estrategia de solución:

  • ¿Qué estructura tienen los datos de entrada?
  • ¿Qué estructura deben tener los datos de salida?
  • ¿Cómo proceso los inputs para generar el output deseado?

In [5]:
def universidades(nombre_archivo):
    archivo = open(nombre_archivo)
    ues = set()
    for linea in archivo:
        rut,u,carrera = linea[:-1].split("#")
        ues.add(u)
    archivo.close()
    return ues

print universidades("data/postulaciones.txt")


set(['USACH', 'UTFSM', 'PUC', 'UCH'])

Pregunta 3.b

Escriba la función postulaciones_u(universidad, arch_estudiantes, arch_postulaciones) que reciba un string con la sigla de la universidad, un string con el nombre del archivo del tipo estudiantes.txt y un string con el nombre del archivo del tipo postulaciones.txt el cual contiene las postulaciones. La función debe retornar un diccionario donde la llave corresponde al rut y nombre del estudiante que postula a la universidad pasada como parámetro y el valor será un conjunto con las carreras a las que postuló el estudiante a dicha institución.

>>> postulaciones_u('UTFSM','estudiantes.txt','postulaciones.txt')
{('17999555-3', 'Daniela Melendez'): 
      set(['Ing. Civil Industrial']),
('16219345-6', 'Alexis Vidal'): 
      set(['Ing. Comercial', 'Piloto Comercial'])}

Estrategia de solución:

  • ¿Qué estructura tienen los datos de entrada?
  • ¿Qué estructura deben tener los datos de salida?
  • ¿Cómo proceso los inputs para generar el output deseado?

In [6]:
def postulaciones_u(universidad_buscada, nombre_arch_estudiantes, nombre_arch_postulaciones):
    # Procesar estudiantes para obtener el nombre a partir del rut
    archivo_estudiantes = open(nombre_arch_estudiantes)
    estudiantes = {}
    for linea in archivo_estudiantes:
        nombre,rut = linea.replace("\n","").split(";")
        estudiantes[rut] = nombre
    archivo_estudiantes.close()
    # Procesar postulaciones, buscando para una universidad en especifico
    archivo_postulaciones = open(nombre_arch_postulaciones)
    postulantes_buscados = {}
    for linea in archivo_postulaciones:
        rut,u,carrera = linea[:-1].split("#")
        if u==universidad_buscada:
            llave = (rut, estudiantes[rut])
            if llave in postulantes_buscados:
                postulantes_buscados[llave].add(carrera)
            else:
                postulantes_buscados[llave] = set([carrera])
    archivo_postulaciones.close()
    return postulantes_buscados
    
print postulaciones_u('UTFSM','data/estudiantes.txt','data/postulaciones.txt')


{('17999555-3', 'Daniela Melendez'): set(['Ing. Civil Industrial']), ('16219345-6', 'Alexis Vidal'): set(['Piloto Comercial', 'Ing. Comercial'])}

Pregunta 3.c

Escriba la función generar_registros(arch_estudiantes,arch_postulaciones) que reciba como parámetros dos string, uno correspondiente al nombre del archivo del tipo estudiantes.txt y otro correspondiente al archivo del tipo postulaciones.txt respectivamente. La función debe crear un archivo cuyo nombre debe ser sigla U.txt para cada universidad del archivo postulaciones. El archivo debe tener la siguiente estructura por línea: rut;nombre;carrera(s) del postulante, separadas por un punto y coma. Ver ejemplo UTFSM.txt. Esta función no retorna nada.

>>> generar_registros('estudiantes.txt','postulaciones.txt')

que genera (entre otros) el archivo UTFSM.txt:

17999555-3;Daniela Melendez;Ing. Civil Industrial
16219345-6;Alexis Vidal;Ing. Comercial;Piloto Comercial
...

Estrategia de solución:

  • ¿Qué estructura tienen los datos de entrada?
  • ¿Qué estructura deben tener los datos de salida?
  • ¿Cómo proceso los inputs para generar el output deseado?

In [7]:
def generar_registros(nombre_arch_estudiantes, nombre_arch_postulaciones):
    ues = universidades(nombre_arch_postulaciones)
    formato_linea = "{0};{1};{2}\n"
    for u in ues:
        nombre_archivo_u = u+".txt"
        archivo = open(nombre_archivo_u, "w")
        postulantes_a_u =  postulaciones_u(u, 
                                           nombre_arch_estudiantes, 
                                           nombre_arch_postulaciones)
        for datos_postulante, set_carreras in postulantes_a_u.items():
            rut, nombre = datos_postulante
            carreras = ";".join(list(set_carreras))
            nueva_linea = formato_linea.format(rut,nombre,carreras)
            archivo.write(nueva_linea)
        archivo.close()
    return None

generar_registros('data/estudiantes.txt', 'data/postulaciones.txt')