Sabemos que enfrentarse a los exámenes de programación en la carrera de Ingeniería de Telecomunicación impone respeto. Pasar de la sintaxis estricta de Java a la flexibilidad de Python en un mismo examen (¡y en 4 horas!) requiere tener los conceptos muy claros.
Como siempre os comento a mis alumnos, la clave para dominar la Programación Orientada a Objetos (POO) no es memorizar, sino entender el porqué de cada línea de código.
Hoy, desde el equipo de la academia, traemos la resolución completa y explicada del simulacro de examen centrado en la gestión de Celdas y Estaciones Base. ¡Vamos a por ese 20/20!
PARTE A: JAVA (10 Puntos)
En esta parte se evalúa la lógica algorítmica clásica y la solidez construyendo clases. Recuerda la norma de oro del examen: prohibido usar streams.
Pregunta 1: Desplazamiento en array (2 puntos)
(a) Teoría: Desplazamiento vs Rotación Circular
- Desplazamiento (Shift): Consiste en mover los elementos de un array hacia una dirección. Los elementos que “salen” por el extremo se pierden, y los huecos que quedan suelen rellenarse con ceros o nulos.
- Rotación circular: Es similar, pero los elementos que “salen” por el lado derecho no se pierden, sino que vuelven a entrar por el lado izquierdo, formando un ciclo infinito.
(b) Implementación de rotarDerecha El truco aquí es usar el operador módulo (%) para normalizar el valor de k (por si nos piden rotar 10 posiciones en un array de 5, que equivaldría a rotar 0) y para calcular la nueva posición circular.
public class UtilidadesArray {
public static int[] rotarDerecha(int[] a, int k) {
if (a == null || a.length == 0) return a;
int n = a.length;
k = k % n; // Normalizamos k si es mayor que la longitud
int[] resultado = new int[n];
for (int i = 0; i < n; i++) {
// Calculamos la nueva posición con aritmética modular
int nuevaPosicion = (i + k) % n;
resultado[nuevaPosicion] = a[i];
}
return resultado;
}
}
Pregunta 2 y 3: Implementación de la clase Celda y sus cálculos (6 puntos)
Aquí unimos la creación de la clase con sus métodos de cálculo (pasar de dBm a mW y calcular el margen de ruido). Es vital validar en el constructor y lanzar la excepción IllegalArgumentException si la frecuencia no es válida.
public class Celda {
// Pregunta 2: Atributos privados
private String id;
private double frecuenciaMHz;
private double potenciaDbm;
// Pregunta 2: Constructor con validación
public Celda(String id, double frecuenciaMHz, double potenciaDbm) {
if (frecuenciaMHz <= 0) {
throw new IllegalArgumentException("La frecuencia debe ser mayor que 0");
}
this.id = id;
this.frecuenciaMHz = frecuenciaMHz;
this.potenciaDbm = potenciaDbm;
}
// Pregunta 2: Getters
public String getId() { return id; }
public double getFrecuenciaMHz() { return frecuenciaMHz; }
public double getPotenciaDbm() { return potenciaDbm; }
// Pregunta 3: Cálculos
public double potenciaMw() {
return Math.pow(10, this.potenciaDbm / 10.0);
}
public double margen(double ruidoDbm) {
return this.potenciaDbm - ruidoDbm;
}
// Método toString (Opcional pero recomendado para imprimir fácil)
@Override
public String toString() {
// Usamos Locale.US si queremos asegurar el punto decimal, o simplemente String.format
return String.format("%s f=%.1f MHz P=%.1f dBm", id, frecuenciaMHz, potenciaDbm);
}
}
Pregunta 4: EstacionBase y las pruebas (2 puntos)
Esta clase gestiona un array estático de objetos Celda. Ojo con lanzar IllegalStateException cuando el array está lleno.
public class EstacionBase {
private String id;
private Celda[] celdas;
private int numCeldas;
public EstacionBase(String id, int cap) {
this.id = id;
this.celdas = new Celda[cap];
this.numCeldas = 0;
}
public void addCelda(Celda c) {
if (numCeldas >= celdas.length) {
throw new IllegalStateException("La Estación Base está llena.");
}
celdas[numCeldas] = c;
numCeldas++;
}
public Celda buscar(String id) {
for (int i = 0; i < numCeldas; i++) {
if (celdas[i].getId().equals(id)) {
return celdas[i]; // Devuelve si coincide
}
}
return null;
}
public Celda mejorCelda(double ruidoDbm) {
if (numCeldas == 0) return null;
Celda mejor = celdas[0];
double maxMargen = mejor.margen(ruidoDbm);
for (int i = 1; i < numCeldas; i++) {
double margenActual = celdas[i].margen(ruidoDbm);
if (margenActual > maxMargen) {
maxMargen = margenActual;
mejor = celdas[i];
}
}
return mejor;
}
public double potenciaMediaDbm() {
if (numCeldas == 0) return 0.0;
double suma = 0.0;
for (int i = 0; i < numCeldas; i++) {
suma += celdas[i].getPotenciaDbm();
}
return suma / numCeldas;
}
// --- MAIN DE PRUEBAS PARA PREGUNTAS 2, 3 Y 4 ---
public static void main(String[] args) {
// Prueba P2
Celda c1 = new Celda("CEL-01", 1800.0, 30.0);
System.out.println(c1.toString()); // Imprime: CEL-01 f=1800.0 MHz P=30.0 dBm
// Prueba P3
System.out.printf("Potencia c1: %.2f mW%n", c1.potenciaMw());
System.out.printf("Margen c1: %.1f dB%n", c1.margen(-95.0));
// Prueba P4
EstacionBase eb = new EstacionBase("EB-1", 10);
eb.addCelda(c1);
eb.addCelda(new Celda("CEL-02", 2100.0, 23.0));
eb.addCelda(new Celda("CEL-03", 900.0, 18.0));
Celda mejor = eb.mejorCelda(-95.0);
System.out.println("Mejor celda: " + mejor.getId());
System.out.printf("Potencia media: %.2f dBm%n", eb.potenciaMediaDbm());
}
}
PARTE B: PYTHON (10 Puntos)
Cambiamos el “chip” a Python. Aquí se busca código limpio, idiomático (“pythonic”) y un buen manejo de diccionarios y listas.
Pregunta 1: Conocimientos básicos (2 puntos)
(a) Diferencia entre list y tuple: La diferencia principal es la mutabilidad. Una lista (list) se puede modificar tras su creación (añadir, borrar, cambiar elementos) y usa corchetes []. Una tupla (tuple) es inmutable (no se puede alterar una vez definida) y usa paréntesis ().
(b) Mini-ejercicios:
# 1. Lambda porcentaje
porcentaje = lambda num, pct: num * (pct / 100)
# 2. f-string
nombre = "TuNombre" # Puedes cambiarlo
print(f"{nombre} - Asignatura: Python se aprende escribiendo codigo todos los dias.")
# 3. Recorrer frecuencias
frecuencias = [700, 800, 900, 1800, 2100, 2600]
for f in frecuencias:
print(f"f={f} MHz")
# 4. Recorrer claves diccionario
mod = {'QPSK': 2, '16QAM': 4, '64QAM': 6}
for clave in mod.keys():
print(clave)
Pregunta 2 y 3: Clase Celda en Python (6 puntos)
Fíjate en cómo implementamos el método dunder __str__ para el formateo y usamos isinstance para validar que el ruido sea numérico en el método margen.
class Celda:
# Pregunta 2
def __init__(self, id_celda: str, frecuencia_mhz: float, potencia_dbm: float):
if frecuencia_mhz <= 0:
raise ValueError("La frecuencia debe ser estrictamente mayor a 0")
self.id = id_celda
self.frecuencia_mhz = frecuencia_mhz
self.potencia_dbm = potencia_dbm
def __str__(self):
return f"{self.id} | f={self.frecuencia_mhz:.1f} MHz | P={self.potencia_dbm:.1f} dBm"
# Pregunta 3
def potencia_mw(self) -> float:
return 10 ** (self.potencia_dbm / 10)
def margen(self, ruido_dbm: float) -> float:
if not isinstance(ruido_dbm, (int, float)):
raise TypeError("El ruido debe ser un valor numérico")
return self.potencia_dbm - ruido_dbm
# --- Pruebas Pregunta 2 y 3 ---
if __name__ == "__main__":
# P2
c1 = Celda('CEL-01', 1800.0, 30.0)
print(c1)
# P3
print(f"Potencia c1: {c1.potencia_mw():.2f} mW")
print(f"Margen c1: {c1.margen(-95.0):.1f} dB")
Pregunta 4: Listas, diccionarios y mejor celda (2 puntos)
Para encontrar la mejor celda, Python nos ofrece la maravillosa función integrada max(), pasándole una función lambda como key.
# Definición de celdas
c1 = Celda('CEL-01', 1800.0, 30.0)
c2 = Celda('CEL-02', 2100.0, 23.0)
c3 = Celda('CEL-03', 900.0, 18.0)
celdas = [c1, c2, c3]
ruido = -95.0
print("\n--- Recorriendo la lista ---")
for c in celdas:
print(f"{c.id} -> margen={c.margen(ruido):.1f} dB")
print("\n--- Recorriendo diccionario de márgenes ---")
# Creamos el diccionario usando "Dictionary Comprehension"
margenes = {c.id: c.margen(ruido) for c in celdas}
for clave in margenes.keys():
print(clave)
print("\n--- Mejor Celda ---")
# Buscamos el objeto celda que nos dé el margen máximo
mejor_celda = max(celdas, key=lambda c: c.margen(ruido))
print(f"Mejor celda: {mejor_celda.id} (margen={mejor_celda.margen(ruido):.1f} dB)")
Conclusión
¡Y con esto tendríamos el 20/20! Si te has atascado en algún paso, no te desanimes. La fluidez en programación se consigue tecleando mucho y equivocándose aún más.
Si necesitas ayuda extra, en nuestra academia tenemos grupos reducidos donde resolvemos exámenes de convocatorias anteriores paso a paso. ¿Qué parte te ha parecido más difícil, la rigidez de Java o la abstracción de Python? ¡Déjanoslo en los comentarios!
Contenido restringido
Comments are closed