COMPARTE ESTE ARTÍCULO

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

Acceso de usuarios existentes
   
Registro de un nuevo usuario
*Campo necesario

Categories:

Tags:

Comments are closed

Estado de acceso
ESTADO DE ACCESO
TRADUCTORES
COMPARTENOS
Insert math as
Block
Inline
Additional settings
Formula color
Text color
#333333
Type math using LaTeX
Preview
\({}\)
Nothing to preview
Insert
error: CONTENIDO PROTEGIDO