Examen MP Datos Resuelto Mayo 2022
Examen MP Datos Resuelto Mayo 2022
Examen MP Datos Resuelto Mayo 2022
Nombre: D.N.I.:
2. (2 p) Las porciones de código siguientes, ¿hacen lo que pide el enunciado? En caso nega.vo, explica por qué:
Acumula en s la suma de los n prime- Imprime m×n veces el mensaje (con Asigna a r el cuadrado de x, pero sólo
ros números impares posiJvos: m>0 y n>0): si x>=0:
s: int = 0 for i in range(1, m): r: int = 0
for i in range(1, n + 1, 2): for j in range(1, n): i: int = 1
s += i print("mensaje") while i <= x:
r += x
i += 1
□Si ⊠No □Si ⊠No ⊠Si □No
Solucion: El valor de s será la suma Solucion: El mensaje se imprimi-
de los impares en el intervalo [1, n], rá (m-1)×(n-1) veces, ya que
que no es lo mismo que la suma de range(x, y) itera desde x hasta
los n primeros impares. y-1
3. (3 p) Escribe en Python la función serie_extraña(), que retorna el valor de la serie SL , uJlizando sus n primeros
términos, siendo n el único parámetro que se pasa a la función:
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
SL = + − − + + + − − − − + + + + + − − − ...
1 2 3
4 5
6
7 8 9 10 11 12 13
14 15
16 17
1 pos. 2 neg. 3 pos. 4 neg. 5 pos. 6 neg.
return suma
Pág. 1 de 5
4. (2 p) Escribe las condiciones para que el condicional imprima el mensaje cuando deba hacerlo:
(a) Suponiendo que M es un tensor NumPy:
if len(msg) % 2 != 0 :
print("La frase msg tiene un número impar de caracteres")
5. (3 p) Rellena el código que falta en el siguiente programa para que los números contenidos en la lista l se distribuyan
en 5 conjuntos diferentes: uno que contenga los números menores o iguales a 3, otro con los mayores que 3 y menores
o iguales que 6, y otro con los mayores que 6. Además, los números de este úlJmo conjunto también se distribuyen en
otros dos conjuntos, los que son pares y los que son impares. La parte final del código que se entrega produce la salida
que puedes ver más abajo.
l: list = [1, 7, 2, 9, 3, 5, 4, 5, 6, 6, 6, 8, 9, 10]
Solución:
Pág. 2 de 5
6. (4 p) Implementa de forma eficiente la función buscar_sublista(), que recibe como parámetros una lista de números,
lista, y un número adicional, suma. La función debe retornar una tupla con dos índices, que determinen una sublista
cuya suma coincida con suma. Si no hay tal sublista se retornará una tupla vacía. Algunos ejemplos:
Siendo x = [1, 9, 1, 1, 1, 2, 2, 3, 7]:
buscar_sublista(x, 6) -> (3, 7) ya que x[3] + x[4] + x[5] + x[6] = 1 + 1 + 2 + 2 = 6
buscar_sublista(x, 9) -> (1, 2) ya que x[1] = 9 = 9
buscar_sublista(x, 10) -> (0, 2) ya que x[0] + x[1] = 1 + 9 = 10
buscar_sublista(x, 100) -> () ya que no hay sublistas que sumen 100
Nota: recuerda que puedes calcular la suma de una sublista pasándosela como argumento a sum().
i j
Secuencia: (0, 1), (0, 2), (0, 3), . . . (1, 2), (1, 3), (1, 4) . . .
Solución: Primer elemento: (i, j) = (0,
1)
(i, j + 1), si sum(lista[i : j]) < suma
Siguiente elemento: (i, j) =
(i + 1, i + 2), en otro caso
Fin de secuencia: i >= len(lista)oj > len(lista)
Elemento encontrado: sum(lista[i : j]) == suma
7. (3 p) Implementa la función zigzag(), que recibe como parámetro un ndarray bidimensional (matriz) y retorna un
ndarray unidimensional (vector) con el contenido de la matriz extraído de ésta mediante recorrido en zig-zag como se
muestra en el ejemplo siguiente:
1 2 3 4
m= 5 6 7 8✻ −→ zigzag(m) retornará 1 5 9 10 6 2 3 7 11 12 8 4
9 10 11 12
Nota: Recuerda que el atributo shape de los objetos ndarray es una tupla con el tamaño en cada dimensión, y que se pueden crear
un ndarray vacío con np.empty(t), siendo t un número entero o una tupla de enteros con las dimensiones del nuevo array.
Solución: Suponiendo que el código comienza con import numpy as np, podríamos hacer:
Versión 1 Versión 2
def zigzag_columnas(matriz: np.ndarray) -> np.ndarray: def zigzag_columnas(matriz: np.ndarray) -> np.ndarray:
filas, columnas = matriz.shape filas, columnas = matriz.shape
# creamos un vector con el tamaño adecuado # creamos un vector con el tamaño adecuado
vector: np.ndarray = np.empty(filas * columnas) vector: np.ndarray = np.empty(filas * columnas)
k: int = 0 k: int = 0
for c in range(columnas): for c in range(columnas):
if c % 2 == 0: if c % 2 == 0:
for f in range(filas): vector[k : k + filas] = matriz[:, c]
vector[k] = matriz[f, c] else:
k += 1 vector[k : k + filas] = matriz[::-1, c]
else: k += filas
for f in range(filas - 1, -1, -1): return vector
vector[k] = matriz[f, c]
k += 1
return vector
Pág. 3 de 5
8. (4 p) Implementa la clase BOW (bag of words), cuyos objetos permiten contar el número de apariciones de palabras en
un texto, entendiendo por palabra el conjunto de caracteres entre espacios en blanco. Los detalles de implementación
son los siguientes:
⊲ Atributos:
◦ Un atributo de Jpo dict, en el que cada clave será una palabra del texto y su dato asociado será un valor entero
indicando cuántas veces se ha contabilizado esa palabra. Este atributo no es accesible desde el exterior de la clase,
ni siquiera para lectura.
◦ Un atributo de Jpo str, que especifica los caracteres que se descartarán en el procesado de los textos1 . No se
podrá modificar una vez construido el objeto, pero sí se podrá consultar.
⊲ Propiedades:
◦ eliminables: sirve para consultar el valor es la cadena de símbolos que se descartan al procesar los textos. Re-
cuerda que no se puede modificar dicha cadena, sólo se puede leer.
◦ núm_palabras, cuyo valor es un número entero indicando cuántas palabras diferentes aparecen en el texto con el
que se creó la bolsa.
◦ núm_total_ocurrencias, cuyo valor es un número entero indicando cuantas palabras (incluyendo repeJciones)
se procesaron en el texto con el que se creó la bolsa.
◦ palabras: cuando se consulta esta propiedad se obJene una cadena de texto con todas las palabras contenidas en
el objeto, separadas por espacio en blanco (generalmente no coincidirá con el texto original, ver ejemplo, línea 9).
Cuando se asigna una cadena de texto a esta propiedad, se vuelve a calcular de nuevo el contenido del diccionario
que lleva el conteo (ver ejemplo más abajo, líneas 5 y 10).
⊲ Métodos:
◦ El método “constructor”, que lleva dos parámetros opcionales: el texto a procesar (su valor por defecto será "") y
la cadena de caracteres eliminables antes del conteo de palabras (su valor por defecto será ".,;-¿?").
◦ El método num_ocurrencias(), que lleva como parámetro obligatorio una palabra y retorna el número de ocu-
rrencias de dicha palabra en la bolsa.
◦ El método “mágico” que permite sumar bolsas de palabras, retornando un nuevo objeto BOW con la bolsa de palabras
resultante de fusionar ambas bolsas (ver ejemplo más abajo). Para poder sumar dos bolsas de palabras, ambas
deben tener el mismo conjunto de símbolos eliminables, que será el que también tenga la bolsa resultante. Si esto
no es así, la operación provocará una excepción con raise ValueError.
◦ El método “mágico” que retorna una cadena representando el contenido de la bolsa, tal como se ve en la salida de
las instrucciones print del ejemplo que se muestra a conJnuación.
Bolsa b1:
6 palabras (4 únicas)
Esto ( 1) *
1 b1: BOW = BOW(texto="Esto es texto, ¿es poco texto?") es ( 2) **
2 print("Bolsa b1:") texto ( 2) **
3 print(b1) poco ( 1) *
4 b2: BOW = BOW()
Bolsa b3:
5 b2.palabras = "Esto es otro texto."
8 palabras (5 únicas)
6 b3: BOW = b1 + b2 Esto ( 2) **
7 print("Bolsa b3:") =⇒ es ( 2) **
8 print(b3) texto ( 2) **
9 print(f"Palabras en b1: '{b1.palabras}'") poco ( 1) *
10 b1.palabras = "-Otro texto-" otro ( 1) *
11 print("\nb1 ha cambiado:")
Palabras en b1: 'Esto es texto poco'
12 print(b1)
b1 ha cambiado:
2 palabras (2 únicas)
Otro ( 1) *
texto ( 1) *
Te puede resultar úJl recordar cómo funcionan los métodos split() y join(). Observa los siguientes ejemplos:
1 Por ejemplo, si este atributo toma el valor "-." y se suministra el texto "sub-índice menor.", en realidad se va a hacer el conteo de palabras del
Pág. 4 de 5
Solución:
from __future__ import annotations
class BOW:
def __init__(self, texto: str = "", eliminables: str = ".,;-¿?") -> None:
# Atributos
self.__eliminables: str = eliminables
self.__palabras: dict = {}
# rellenamos el atributo usando el setter, para el procesamiento
# del texto suministrado
self.palabras = texto
@property
def eliminables(self) -> str:
return self.__eliminables
@property
def palabras(self) -> str:
return " ".join(list(self.__palabras))
@palabras.setter
def palabras(self, texto: str) -> None:
lista_caracteres: list = [c for c in texto if c not in self.__eliminables]
texto_aux: str = "".join(lista_caracteres)
# texto_aux es el resultado de quitar los caracteres eliminables a texto
lista_palabras: list = texto_aux.split()
# vaciamos el diccionario, por si hubiese datos
self.__palabras = {}
for p in lista_palabras:
self.__palabras[p] = self.núm_ocurrencias(p) + 1
@property
def núm_total_ocurrencias(self) -> int:
# return sum(list(self.__palabras.values()))
total: int = 0
for p in self.__palabras:
total += self.__palabras[p]
return total
@property
def núm_palabras(self) -> int:
return len(self.__palabras)
return texto
Pág. 5 de 5