3  2019-06-18
Examen de Inteligencia de los Negocios

Fecha de publicación

18 de junio de 2019

Grado: Inteligencia de los Negocios
Fecha: 18 de Junio de 2019

Ejercicio 3.1  

  1. Clonar con git el repositorio con la url https://github.com/asalberceu/examen-fundamentos-computadores-2019-06-18-parcial1.git.
  2. Crear una rama con los apellidos del alumno en mayúsculas y separados por un guión, es decir, <APELLIDO1-APELLIDO2>, y convertir esta rama en la rama activa.
  3. Crear el fichero ejercicio1.3.txt que contenga la salida del comando de Git que muestra el historial de commits del repositorio, mostrando un commit por línea.
  4. Crear un fichero ejercicio1.4.txt que contenga la salida del comando que muestra las diferencias entre el primer y el tercer commits del repositorio.
  5. Crear un fichero ejercicio1.5.txt que contenga la salida del comando de Git que muestra los repositorios remotos configurados junto con sus urls.
  6. Añadir todos los cambios a la zona temporal de intercambio y hacer un commit con el mensaje “Añadidas respuestas ejercicio 1.”
> git clone https://github.com/asalberceu/examen-fundamentos-computadores-2019-06-18-parcial1.git
> cd examen-fundamentos-computadores-2019-06-18-parcial1.git
> git checkout -b SANCHEZ-ALBERCA
> git log --oneline > ejercicio1.3.txt
> git diff f9ed835 a485ced > ejercicio1.4.txt
> git remote -v > ejercicio1.5.txt
> git add . 
> git commit -m "Añadida respuestas."

Ejercicio 3.2 A lo largo de un curso se realizan dos exámenes parciales. Para aprobar el curso la nota media debe ser mayor o igual que 5 siempre y cuando en ambos parciales se tenga al menos un 4. Escribir un programa que pregunte al usuario la nota de los dos parciales y muestre por pantalla si el alumno ha aprobado el curso o si no, y en caso de no haber aprobado, qué parcial tiene que repetir por tener menos de 4 en él.

# Pedimos al usuario que introduzca las notas de las asignaturas y las convertimos en números reales
nota1 = float(input('Introduce la nota de la primera parte: '))
nota2 = float(input('Introduce la nota de la segunda parte: '))
# Comprobamos si ambas notas son mayores o iguales que 4 y si la media es mayor o igual que 5
if nota1 >= 4 and nota2 >= 4 and ((nota1 + nota2) / 2) >= 5:  # Las dos notas son mayores que 4 y la media mayor o igual que 5
    print('Has aprobado')
else: # La nota media es menor que 5 o alguna nota es menor que 4 (suspenso)
    print('Has suspendido')
    # Comprobamos si la primera nota es menor que 4
    if nota1 < 4:
        print('Tienes que repetir el primer parcial')
    # Comprobamos si la segunda nota es menor que 4
    if nota2 < 4:
        print('Tienes que repetir el segundo parcial')
Introduce la nota de la primera parte:  3
Introduce la nota de la segunda parte:  8
Has suspendido
Tienes que repetir el primer parcial

Ver notebook de la solución en Colab

Ejercicio 3.3 Un n-grama es una secuencia de \(n\) caracteres consecutivos de una cadena. Por ejemplo, los 3-gramas de la cadena 'Python' son 'Pyt', 'yth', 'tho' y 'hon'. Escribir un programa que pregunte por una cadena y un número entero positivo \(n\) y muestre por pantalla todos los n-gramas de la cadena.

# Pedimos al usuario que introduzca una palabra y un número entero positivo
palabra = input('Introduce una palabra: ')
n = int(input('Introduce un número entero positivo: '))
# Recorremos las posiciones de la palabra desde el inicio hasta la longitud de la palabra menos n + 1. 
# No tiene sentido seguir ya que las subcadenas después de esa posición tendrían longitud menor que n.
for i in (range(len(palabra) - n + 1)):
    # Mostramos el n-grama que empieza en la posición i
    print(palabra[i:i+n])
Introduce una palabra:  Python
Introduce un número entero positivo:  3
Pyt
yth
tho
hon

Ver notebook de la solución en Colab

Ejercicio 3.4 Escribir un programa que elimine de una lista dada todos los elementos repetidos y muestre por pantalla los elementos de la lista sin repeticiones.

La solución de este ejercicio no está disponible en el repositorio de origen.

Carpeta de soluciones del examen

Ejercicio 3.5 Definir funciones para codificar y decodificar mensajes en código morse.

  1. Definir una función para codificar una palabra en código morse. Debe cumplir los siguientes requisitos:

    • Debe usarse el diccionario que se da.
    • El único parámetro de entrada de la función es una cadena con una palabra.
    • Debe devolver una cadena con el código morse correspondiente a la palabra, separando los bloques de código correspondientes a cada letra por punto y coma ;.
  2. Definir una función para decodificar una palabra en código morse. Debe cumplir los siguientes requisitos:

    • A partir del diccionario que se da se debe crear el diccionario invertido, es decir, un diccionario cuyas claves son los códigos morse y sus valores las letras correspondientes. Se valorará especialmente el uso de comprensión de diccionarios.
    • El único parámetro de entrada de la función es una cadena de código morse, donde los bloques de código correspondientes a cada letra van separados por puntos y coma ;.
    • Debe devolver una cadena con la palabra decodificada.
  3. Definir una función para codificar un mensaje en código morse. Debe cumplir los siguientes requisitos:

    • Debe usarse la función anterior para codificar palabras.
    • El único parámetro de entrada de la función es una cadena con un mensaje (palabras separadas con espacios).
    • Debe devolver una cadena con las palabras del mensaje codificadas y separadas por espacios.
    • Se valorará especialmente el uso de programación funcional.
  4. Definir una función para decodificar un mensaje en código morse. Debe cumplir los siguientes requisitos:

    • Debe usarse la función anterior para decodificar palabras.
    • El único parámetro de entrada de la función es una cadena con un mensaje en código morse (letras separadas por punto y coma, y palabras separadas con espacios).
    • Debe devolver una cadena con las palabras del mensaje decodificadas y separadas por espacios.
    • Se valorará especialmente el uso de programación funcional.
# Diccionario con la codificación morse
morse = {'A': '.-',     'B': '-...',   'C': '-.-.', 
         'D': '-..',    'E': '.',      'F': '..-.',
         'G': '--.',    'H': '....',   'I': '..',
         'J': '.---',   'K': '-.-',    'L': '.-..',
         'M': '--',     'N': '-.',     'O': '---',
         'P': '.--.',   'Q': '--.-',   'R': '.-.',
         'S': '...',    'T': '-',      'U': '..-',
         'V': '...-',   'W': '.--',    'X': '-..-',
         'Y': '-.--',   'Z': '--..'}


def codificar_palabra(palabra):
    """
    Función que codifica una palabra en morse.
    Parámetros:
        palabra: Una cadena con una palabra.
    Devuelve:
        El código morse correspondiente a la palabra con los bloques de código de cada letra separados por punto y coma.
    """
    # Creamos una cadena vacía para ir añadiendo las letras codificadas
    palabra_codificada = ''
    # Recorremos los caracteres de la palabra
    for i in palabra:
        # Accedemos al diccionario con la clave correspondiente al caracter y añadimos el valor (el código morse) a la palabra codificada
        palabra_codificada += morse[i.upper()] + ';' # Añadimos un punto y coma entre caracter y caracter.
    return palabra_codificada


def decodificar_palabra(palabra):
    """
    Función que decodifica una palabra en morse.
    Parámetros:
        palabra: Es una cadena con bloques de código morse separados por el caracter ;.
    Devuelve:
        La palabra decodificada.
    """

    # A partir del diccionario morse construimos otro diccionario invertido, es decir, cuyas claves sean los códigos morse y cuyos valores sean las letras asociadas.
    # Recorremos los pares del diccionario morse e invertimos las claves y los valores y devolvemos un diccionario mediante comprensión de diccionarios.
    morse_invertido = {value:key for key, value in morse.items()}
    # Creamos una cadena vacía para ir añadiendo las letras decodificadas.
    palabra_decodificada = ''
    # Dividimos el código morse por el punto y coma y recorremos la lista de códigos resultante.
    for i in palabra.split(';'):
        # Accedemos al diccionario invertido con la clave correspondiente al código morse y añadimos el valor (el caracter decodificado) a la palabra decodificada.
        palabra_decodificada += morse_invertido[i]
    return palabra_decodificada


def codificar_mensaje(mensaje):
    """
    Función que codifica un mensaje en morse.
    Parámetros:
        mensaje: Una cadena con palabras separadas por espacios.
    Devuelve:
        El código morse correspondiente al mensaje con letras separadas por punto y coma y palabras separadas por espacio.
    """
    # Creamos una cadena con un espacio para ir añadiendo las palabras codificadas.
    mensaje_codificado = ' '
    # Dividimos el mensaje de entrada por el espacio y obtenemos una lista de palabras.
    mensaje = mensaje.split()
    # Aplicamos la función codificar_palabra a cada palabra de la lista y obtenemos una lista con las palabras codificadas.
    palabras_codificadas = list(map(codificar_palabra, mensaje))
    # Concatenamos todas las palabras de la lista en una cadena separadas por un espacio.
    return mensaje_codificado.join(palabras_codificadas)


def decodificar_mensaje(mensaje):
    """
    Función que decodifica un mensaje en morse.
    Parámetros:
        mensaje: Es una cadena código morse con letras separadas por punto y coma y palabras separadas por espacio.
    Devuelve:
        El mensaje decodificado.
    """
    # Creamos una cadena con un espacio para ir añadiendo las palabras decodificadas.
    mensaje_decodificado = ' '
    # Dividimos el mensaje de entrada por el espacio y obtenemos una lista de palabras codificadas.
    mensaje = mensaje.split()
    # Aplicamos la función decodificar_palabra a cada palabra de la lista y obtenemos una lista con las palabras decodificadas.
    palabras_decodificadas = list(map(decodificar_palabra, mensaje))
    # Concatenamos todas las palabras de la lista en una cadena separadas por un espacio.
    return mensaje_decodificado.join(palabras_decodificadas)


# Llamada a las funciones de prueba
print(codificar_palabra('Python')) #Debe devolver '.--.;-.--;-;....;---;-.;'
print(decodificar_palabra('.--.;-.--;-;....;---;-.')) #Debe devolver 'PYTHON'
print(codificar_mensaje('Hola Python')) #Debe devolver '....;---;.-..;.-; .--.;-.--;-;....;---;-.'
print(decodificar_mensaje('....;---;.-..;.- .--.;-.--;-;....;---;-.')) #Debe devolver 'HOLA PYTHON'
.--.;-.--;-;....;---;-.;
PYTHON
....;---;.-..;.-; .--.;-.--;-;....;---;-.;
HOLA PYTHON

Ver notebook de la solución en Colab

Ejercicio 3.6 La url https://datos.madrid.es/egob/catalogo/300117-0-arrendamiento-programas.csv apunta a un fichero en formato csv con datos de los arrendamientos de viviendas de la Empresa Municipal de la Vivienda del Ayuntamiento de Madrid.

  1. Construir una función que abra un fichero con el formato anterior y devuelva una lista cuyos elementos son a su vez las listas que contienen los datos de cada línea del fichero menos la primera línea. Debe cumplir los siguientes requisitos:

    • La función recibirá como único parámetro la url del fichero.
    • Debe leer el fichero por líneas y para cada línea debe dividir la línea por el separador de campos (punto y coma) y guardar los datos en una lista.
    • Debe devolver la lista con las listas de datos obtenidas a partir de cada línea.
  2. Construir una función que reciba una lista de listas como la que devuelve la función anterior y devuelva otra lista con los nombres de los distritos contenidos en la lista. Debe cumplir los siguientes requisitos:

    • La función recibirá como único parámetro una lista de listas con las viviendas arrendadas por distrito.
    • Debe recorrer la lista de listas y para cada lista debe extraer el nombre del distrito y añadirlo a una lista con los distritos.
    • Debe devolver la lista de distritos.
  3. Construir una función que reciba una lista de listas como la que devuelve la primera función y una lista de nombres de distritos y devuelva la lista con las listas correspondientes a los distritos indicados. Debe satisfacer los siguientes requisitos:

    • La función recibirá como parámetros una lista de listas con las viviendas arrendadas por distrito y otra lista con nombres de distritos.
    • Debe recorrer la lista de viviendas arrendadas y añadir a otra lista nueva las líneas correspondientes a los distritos indicados en la segunda lista.
    • Debe devolver la nueva lista con las listas correspondientes a los distritos indicados.
  4. Construir una función que reciba una lista como la que devuelve la primera función y devuelva un diccionario cuyas claves sean los nombres de distrito y cuyos valores sean el total de viviendas arrendadas en el distrito. Debe cumplir los siguientes requisitos:

    • La función recibirá como único parámetro la lista con las viviendas arrendadas por distrito.
    • Debe recorrer la lista de listas y para cada lista extraer el nombre del distrito y el total de viviendas arrendadas en el distrito y añadir el par a un diccionario.
    • Debe devolver un diccionario con un par para cada lista de la lista, cuya clave sea el nombre del distrito y cuyo valor sea el número total de viviendas arrendadas en ese distrito.

Solución 1 Usando comprensión de listas y diccionarios.

def leer_fichero(url):
    """
    Función que abre un fichero de texto desde una url y devuelve una lista de listas con los datos del fichero.
    Parámetros:
        url: URL del fichero de texto en formato csv donde cada registro aparece en una línea y los campos están separados por punto y coma `;`.
    Devuelve:
        Una lista cuyos elementos son a su vez listas que contienen los datos de cada línea del fichero menos la primera línea.
    """
    # Carga del módulo necesario para acceder a un fichero de internet.
    from urllib import request
    from urllib.error import URLError
    # Abrimos el fichero con la url dada.
    try:
        f = request.urlopen(url)
    except URLError: # Si se produce un error al acceder a la url informamos devolvemos una cadena informando de ello.
        return('¡La url ' + url + ' no existe!')
    # Leemos los datos del fichero en una cadena.
    datos = f.read()
    # Decodificamos los datos con la codificación latin1.
    datos = datos.decode('latin1')
    # Creamos una lista con las líneas del fichero dividiendo la cadena por el cambio de línea.
    datos = datos.split('\n')
    # Eliminamos la primera línea que no contiene información interesante.
    datos.pop(0)
    # Recorremos las líneas de la lista y para cada línea creamos una lista con los datos separando por el punto y coma. 
    # Devolvemos la lista de listas mediante comprensión de listas.
    datos_viviendas = [i.split(';') for i in datos]
    return datos_viviendas


def distritos(datos_viviendas):
    """
    Función recibe una lista de listas con los datos de la viviendas arrendadas y devuelve los distritos.
    Parámetros:
        datos_viviendas: Es una lista de listas como la que devuelve la función leer_fichero donde cada lista contienen los datos de viviendas arrendadas de un distrito. 
    Devuelve:
        Una lista con los distritos correspondientes a cada lista.
    """
    # Recorremos la lista de listas y para cada lista accedemos el primer elemento que contiene el nombre del distrito. 
    # Devolvemos la lista de distritos mediante comprensión de listas.
    distritos = [i[0] for i in datos_viviendas[1:]]
    return distritos


def filtrar_distritos(datos_viviendas, distritos):
    """
    Función que recibe una lista de listas con los datos de las viviendas arrendadas y una lista de nombres de distritos y devuelve una lista con las listas correspondientes a los distritos indicados
    Parámetros:
        datos_viviendas: Es una lista de listas como la que devuelve la función leer_fichero donde cada lista contienen los datos de viviendas arrendadas de un distrito. 
        distritos: Una lista de cadenas con nombres de distritos.
    Devuelve:
        Una lista con las listas que contienen los datos de las viviendas arrendadas de los distritos indicados.
    """
    # Recorremos la lista de listas y nos quedamos con las listas que cumplan que su primer elemento (el nombre del distrito) está en la lista de distritos. 
    # Devolvemos la lista de listas filtrada mediante comprensión de listas.
    datos_distritos = [i for i in datos_viviendas if i[0] in distritos]
    return datos_distritos


def viviendas_distritos(datos_viviendas):
    """
    Función que recibe una lista de listas con los datos de las viviendas arrendadas y devuelve un diccionario con los nombres de los distritos y el número total de viviendas arrendadas en el distrito.
    Parámetros:
        datos_viviendas: Es una lista de listas como la que devuelve la función leer_fichero donde cada lista contienen los datos de viviendas arrendadas de un distrito. 
    Devuelve:
        Un diccionario cuyas claves son los nombres de los distritos y cuyos valores son el número total de viviendas arrendadas en cada distrito.
    """
    # Recorremos la lista de listas y para cada lista accedemos el primer elemento que contiene el nombre del distrito y al segundo elemento que contiene el total de viviendas arrendadas.
    # Devolvemos el diccionario formado por los pares con clave el nombre del distrito y valor el total de viviendas arrendadas mediante comprensión de diccionarios.
    viviendas = {i[0]:i[1] for i in datos_viviendas}
    return viviendas



# Llamada a las funciones de prueba
datos = leer_fichero('https://datos.madrid.es/egob/catalogo/300117-0-arrendamiento-programas.csv')
print(distritos(datos))
datos_filtrados = filtrar_distritos(datos, ['CHAMBERI', 'HORTALEZA'])
print(viviendas_distritos(datos_filtrados))  #Devuelve un diccionario con el número total de viviendas arrendadas en Chamberí y Hortaleza.
['ARGANZUELA', 'BARAJAS', 'CARABANCHEL', 'CENTRO', 'CHAMBERI', 'CIUDAD LINEAL', 'FUENCARRAL-EL PARDO', 'HORTALEZA', 'LATINA', 'MONCLOA', 'MORATALAZ', 'PUENTE DE VALLECAS', 'RETIRO', 'SALAMANCA', 'SAN BLAS', 'TETUAN', 'USERA', 'VALLECAS VILLA', 'VICALVARO', 'VILLAVERDE', 'TOTAL', '', '']
{'CHAMBERI': '3', 'HORTALEZA': '12'}

Solución 2 Sin comprensión de listas y diccionarios.

def leer_fichero(url):
    """
    Función que abre un fichero de texto desde una url y devuelve una lista de listas con los datos del fichero.
    Parámetros:
        url: URL del fichero de texto en formato csv donde cada registro aparece en una línea y los campos están separados por punto y coma `;`.
    Devuelve:
        Una lista cuyos elementos son a su vez listas que contienen los datos de cada línea del fichero menos la primera línea.
    """
    # Carga del módulo necesario para acceder a un fichero de internet.
    from urllib import request
    from urllib.error import URLError
    # Abrimos el fichero con la url dada.
    try:
        f = request.urlopen(url)
    except URLError: # Si se produce un error al acceder a la url informamos devolvemos una cadena informando de ello.
        return('¡La url ' + url + ' no existe!')
    # Leemos los datos del fichero en una cadena.
    datos = f.read()
    # Decodificamos los datos con la codificación latin1.
    datos = datos.decode('latin1')
    # Creamos una lista con las líneas del fichero dividiendo la cadena por el cambio de línea.
    datos = datos.split('\n')
    # Eliminamos la primera línea que no contiene información interesante.
    datos.pop(0)
    # Creamos una lista vacía para ir añadiendo los datos de cada línea.
    datos_viviendas = []
    # Recorremos las listas de la lista
    for i in datos:
        # Para cada línea creamos una lista con los datos separando por el punto y coma y la añadimos a la lista principal.
        datos_viviendas.append(i.split(';'))
    return datos_viviendas


def distritos(datos_viviendas):
    """
    Función recibe una lista de listas con los datos de la viviendas arrendadas y devuelve los distritos.
    Parámetros:
        datos_viviendas: Es una lista de listas como la que devuelve la función leer_fichero donde cada lista contienen los datos de viviendas arrendadas de un distrito. 
    Devuelve:
        Una lista con los distritos correspondientes a cada lista.
    """
    # Creamos una lista vacía para ir añadiendo los distritos.
    distritos = []
    
    # Recorremos la lista de listas (empezando en el segundo elemento ya que el primero contiene los nombres de las columnas)
    for i in datos_viviendas[1:]: 
        # Para cada lista accedemos el primer elemento que contiene el nombre del distrito y lo añadimos a la lista de distritos.
        distritos.append(i[0])
    return distritos


def filtrar_distritos(datos_viviendas, distritos):
    """
    Función que recibe una lista de listas con los datos de las viviendas arrendadas y una lista de nombres de distritos y devuelve una lista con las listas correspondientes a los distritos indicados
    Parámetros:
        datos_viviendas: Es una lista de listas como la que devuelve la función leer_fichero donde cada lista contienen los datos de viviendas arrendadas de un distrito. 
        distritos: Una lista de cadenas con nombres de distritos.
    Devuelve:
        Una lista con las listas que contienen los datos de las viviendas arrendadas de los distritos indicados.
    """
    # Creamos una lista vacía para ir añadidiendo las listas fitradas.
    datos_distritos = []
    # Recorremos la lista de listas (empezando en el segundo elemento ya que el primero contiene los nombres de las columnas)
    for i in datos_viviendas[1:]:
        # Comprobamos si el primer elemento de que contiene el nombre del distrito está en la lista de distritos.
        if i[0] in distritos:
            # Si el distrito está en la lista añadimos la lista con los datos del distrito a la lista filtrada.
            datos_distritos.append(i)
    return datos_distritos


def viviendas_distritos(datos_viviendas):
    """
    Función que recibe una lista de listas con los datos de las viviendas arrendadas y devuelve un diccionario con los nombres de los distritos y el número total de viviendas arrendadas en el distrito.
    Parámetros:
        datos_viviendas: Es una lista de listas como la que devuelve la función leer_fichero donde cada lista contienen los datos de viviendas arrendadas de un distrito. 
    Devuelve:
        Un diccionario cuyas claves son los nombres de los distritos y cuyos valores son el número total de viviendas arrendadas en cada distrito.
    """
    # Creamos un diccionario vacío para añadir las viviendas arrendadas en cada distrito.
    viviendas = {}
    # Recorremos la lista de listas
    for i in datos_viviendas:
        # Para cada lista accedemos el primer elemento que contiene el nombre del distrito y al segundo elemento que contiene el total de viviendas arrendadas y añadimos el par al didcionario.
        viviendas[i[0]] = i[1]
    return viviendas


# Llamada a las funciones de prueba
datos = leer_fichero('https://datos.madrid.es/egob/catalogo/300117-0-arrendamiento-programas.csv')
print(distritos(datos))
datos_filtrados = filtrar_distritos(datos, ['CHAMBERI', 'HORTALEZA'])
print(viviendas_distritos(datos_filtrados))  #Devuelve un diccionario con el número total de viviendas arrendadas en Chamberí y Hortaleza.
['ARGANZUELA', 'BARAJAS', 'CARABANCHEL', 'CENTRO', 'CHAMBERI', 'CIUDAD LINEAL', 'FUENCARRAL-EL PARDO', 'HORTALEZA', 'LATINA', 'MONCLOA', 'MORATALAZ', 'PUENTE DE VALLECAS', 'RETIRO', 'SALAMANCA', 'SAN BLAS', 'TETUAN', 'USERA', 'VALLECAS VILLA', 'VICALVARO', 'VILLAVERDE', 'TOTAL', '', '']
{'CHAMBERI': '3', 'HORTALEZA': '12'}

Ver notebook de la solución en Colab