1. Introducción

Modularizar es una estrategia de resolución de problemas y de ingenieria de software que consiste en dividir el problema original en un conjunto de subproblemas. Consiste en aplicar una estrategia heurística fundamental: descomposición y recombinación. Esta heurística consiste en poder descomponer un todo en sus partes y poder recombinar las partes en un todo.

En programación y en el diseño de algorítmos, un buen diseño estructurado persigue elaborar algorítmos que cumplan la propiedad de modularidad, esto es dado un problema que se pretende resolver mediante la utilización de una computadora, se busca dividir dicho programa en módulos independientes.

El diseño estructurado incluye la descomposición, para lo cual se requiere un adecuado análisis de dicho problema, siendo necesario definir primeramente el problema. Merece la pena el esfuerzo de dividir un problema grande en subproblemas más pequeños.

Ahora la cuestión es ¿cómo realizar la descomposición?; una manera es realizando un estudio descendente (top-down) que nos lleve desde la concepción del problema (programa o algorítmo) global hasta identificar sus partes (módulos). Esta técnica se repite una y otra vez refinando el problema hasta obtener subproblemas suficientemente pequeños, que puedan ser resueltos por módulos que cumplan, en la medida de lo posible, las características deseables en un modulo en el ámbito de la programación.

En cada paso del refinamiento, una o varias instrucciones del programa dado, se descomponen en instrucciones mas detalladas.

Cuándo parar el refinamiento?. Un refinamiento excesivo podría dar lugar a un número tan grande de módulos que haría poco práctica la descomposición. Se tendrán en cuenta este criterio para dejar de descomponer: Cuando el MÓDULO definido realice una única tarea, lo suficientemente simple y entendible, y no existan subtareas que requieran descomposición

2. Problemas

2.1 Día de la semana

Problema: Solicitar al usuario el número de un dia de la semana ([1-7]) e indicar a que día corresponde (en letras).

ALGORITMO dia() RETORNA ∅
  (* este alg. dado un dia en formato numérico [1-7]
     obtiene el nombre del dia de la semana *)
  ENTERO diaSemana 
  TEXTO diaTexto
  diaSemana <- 1
  ESCRIBIR("Ingrese un dia de la semana en formato numérico: ")
  LEER(diaSemana)
  SI (diaSemana>0 AND diaSemana<8) ENTONCES
    SEGÚN (diaSemana) HACER
       1: diaTexto <- "Lunes"
       2: diaTexto <- "Martes"
       3: diaTexto <- "Miércoles"
       4: diaTexto <- "Jueves"
       5: diaTexto <- "Viernes"
       6: diaTexto <- "Sabado"
       7: diaTexto <- "Domingo"
       Vo: diaTexto <- "Dia inválido"
    FIN SEGÚN
    ESCRIBIR("El dia "+diaSemana
        +" de la semana corresponde a: "+diaTexto )
  SINO
     ESCRIBIR("Dia no válido")
  FIN SI
FIN ALGORITMO dia
import java.util.Scanner;

public class Dia {
public static void main(String[] args) {
  /* este alg. dado un dia en formato numérico [1-7]
     obtiene el nombre del dia de la semana */
  Scanner entrada = new Scanner(System.in);
  int diaSemana = 1;
  String diaTexto= " ";
  System.out.println("Ingrese un dia de la semana en formato numérico: ");
  diaSemana = entrada.nextInt();
  if (diaSemana>0 && diaSemana<8){
    switch (diaSemana){
       case 1: diaTexto = "Lunes"; break;
       case 2: diaTexto = "Martes"; break;
       case 3: diaTexto = "Miércoles"; break;
       case 4: diaTexto = "Jueves"; break;
       case 5: diaTexto = "Viernes"; break;
       case 6: diaTexto = "Sabado"; break;
       case 7: diaTexto = "Domingo"; break;    
    }
    System.out.println("El dia "+diaSemana
        +" de la semana corresponde a: "+diaTexto );
  }   
  else 
    System.out.println("Dia no válido");
}
}

Descargar Archivo Dia.java

Traza del algoritmo suponiendo que el usuario ingresa el valor 3:

Algoritmo Principal:

diaSemana diaTexto salida
1 Miércoles Ingrese un dia de la semana en formato numérico:
3 El dia 3 de la semana corresponde a: Miércoles

2.2 Dia de la Semana (módulo)

Problema: Solicitar al usuario el número de un mes del año ([1-12]) e indicar a que mes corresponde (en letras).

MÓDULO obtenerDia(ENTERO diaSem) RETORNA TEXTO
  (* obtiene el dia de la semana (texto) a partir
     de un dia expresado en un dígito [1,7]
     dia: dia expresado en un número
     retorna texto del dia de la semana*)
  TEXTO diaTexto 
  SEGÚN (diaSem) HACER
       1: diaTexto <- "Lunes"
       2: diaTexto <- "Martes"
       3: diaTexto <- "Miercoles"
       4: diaTexto <- "Jueves"
       5: diaTexto <- "Viernes"
       6: diaTexto <- "Sabado"
       7: diaTexto <- "Domingo"
       Vo: diaTexto <- "Dia inválido"
  FIN SEGÚN
  RETORNA diaTexto
FIN MÓDULO obtenerDia

ALGORITMO diaModulo() RETORNA ∅
(* este alg. dado un mes en formato numérico
   obtiene el nombre de un mes *)
  ENTERO diaSemana
  TEXTO diaTexto
  diaSemana <- 1
  ESCRIBIR("ingrese un dia de la semana en formato numérico:")
  LEER(diaSemana)
  SI (diaSemana>0 AND diaSemana<8) ENTONCES
    diaTexto <- obtenerDia(diaSemana);   
    ESCRIBIR("El dia "+diaSemana
       +" de la semana corresponde a: "+diaTexto )
  SINO 
    ESCRIBIR("Dia no válido")
  FIN SI
FIN ALGORITMO diaModulo 
import java.util.Scanner;

public class DiaModulo {
    
public static String obtenerDia(int dia){
  /* obtiene el dia de la semana (texto) a partir
     de un dia expresado en un dígito [1,7]
     dia: dia expresado en un número
     retorna texto del dia de la semana*/
 String diaTexto=" "; 
 switch (dia){
    case 1: diaTexto = "Lunes"; break;
    case 2: diaTexto = "Martes"; break;
    case 3: diaTexto = "Miércoles"; break;
    case 4: diaTexto = "Jueves"; break;
    case 5: diaTexto = "Viernes"; break;
    case 6: diaTexto = "Sábado"; break;
    case 7: diaTexto = "Domingo"; break;    
  }
  return diaTexto; 
}

public static void main(String[] args) {
/* este alg. dado un mes en formato numérico
   obtiene el nombre de un mes */
Scanner entrada = new Scanner(System.in);
int diaSemana = 1;
String diaTexto= " ";
System.out.println("ingrese un dia de la semana en formato numérico: ");
diaSemana = entrada.nextInt();
if (diaSemana>0 && diaSemana<8){
   diaTexto = obtenerDia(diaSemana);   
   System.out.println("El dia "+diaSemana
     +" de la semana corresponde a: "+diaTexto );
   }   
else 
   System.out.println("Dia no válido");
}
}

Descargar Archivo DiaModulo.java

La traza del algoritmo suponiendo que el usuario ingresa el valor 3, debe mostrar la traza del algoritmo principal y del algoritmo invocado (obtenerDia):

Algoritmo Principal:

diaSemana diaTexto salida
1 Miércoles Ingrese un dia de la semana en formato numérico:
3 El dia 3 de la semana corresponde a: Miércoles

obtenerDia:

diaSem diaTexto valor retornado
3 Miércoles Miercoles

2.3 Mes del Año

Problema: Solicitar al usuario el número de un mes del año ([1-12]) e indicar a que mes corresponde (en letras).

MÓDULO obtenerMes(ENTERO mes) RETORNA ∅
  (* dado un mes del año en formato numérico [1-12]
     permite obtener el mes del año en formato texto
     mes: mes del año en formato numérico
     retorna mes en formato texto *)
 TEXTO mesLetras  
 SEGÚN (mes) HACER
     1: mesLetras <- "Enero"
     2: mesLetras <- "Febrero"
     3: mesLetras <- "Marzo"
     4: mesLetras <- "Abril"
     5: mesLetras <- "Mayo";
     6: mesLetras <- "Junio"
     7: mesLetras <- "Julio"
     8: mesLetras <- "Agosto"
     9: mesLetras <- "Setiembre"
     10: mesLetras <- "Octubre"
     11: mesLetras <- "Noviembre"
     12: mesLetras <- "Diciembre"
     default: mesLetras <- "Inválido"
     }
  RETORNAR mesLetras
FIN MÓDULO obtenerMes

ALGORITMO mes() RETORNA ∅
  (* este alg. dado un mes en formato numérico
   obtiene el nombre de un mes *)
  ENTERO mesA
  TEXTO mesTexto
  ESCRIBIR("ingrese un mes del 
            año en formato numérico: ")
  LEER(mesA)
  mesTexto <- obtenerMes(mesA)
  ESCRIBIR("El mes "+mesA+" es : "+mesTexto )
FIN ALGORITMO mes
import java.util.Scanner;

public class Mes {
public static String obtenerMes(int mes){
   /* dado un mes del año en formato numérico [1-12]
         permite obtener el mes del año en formato texto
        mes: mes del año en formato numérico
        retorna mes en formato texto */
   String mesLetras = " ";  
   switch (mes) {
     case 1: mesLetras = "Enero"; break;
     case 2: mesLetras = "Febrero"; break;
     case 3: mesLetras = "Marzo"; break;
     case 4: mesLetras = "Abril"; break;
     case 5: mesLetras = "Mayo"; break;
     case 6: mesLetras = "Junio"; break;
     case 7: mesLetras = "Julio"; break;
     case 8: mesLetras = "Agosto"; break;
     case 9: mesLetras = "Setiembre"; break;
     case 10: mesLetras = "Octubre"; break;
     case 11: mesLetras = "Noviembre"; break;
     case 12: mesLetras = "Diciembre"; break;
     default: mesLetras = "Inválido"; break;
     }
return mesLetras;
}
    
public static void main(String[] args) {
/* este alg. dado un mes en formato numérico
   obtiene el nombre de un mes */
Scanner entrada = new Scanner(System.in);
int mesA;
mesA= 1;
String mesTexto;
System.out.println("ingrese un mes del 
            año en formato numérico: ");
mesA = entrada.nextInt();
mesTexto = obtenerMes(mesA);
System.out.println("El mes "+mesA+" es : "+mesTexto );
}
}

Descargar Archivo Mes.java

Traza del algoritmo suponiendo que el usuario ingresa el valor 3. La traza debe mostrar la traza del algoritmo principal y del algoritmo invocado (obtenerMes):

Algoritmo Principal:

mesA mesTexto salida
1 Marzo Ingrese un mes del año en formato numérico:
3 El mes 3 es Marzo

obtenerMes:

mes mesLetra valor retornado
3 Marzo Marzo

2.4 Conversor de Temperaturas

Problema: Solicitar al usuario que ingrese una temperatura en grados Celsius o Fahrenheit y luego transformar dicha temperatura ingresada a la otra escala. De acuerdo a las siguientes fórmulas:

  • Conversión de Fahrenheit a Celsius: °C = (°F - 32) * (5/9)
  • Conversión de Celsius a Fahrenheit: °F = °C * (9/5) + 32
MÓDULO celsiusToFahrenheit(REAL grados) RETORNA REAL
  (* convierte de escala Celsius a Fahrenheit 
    grados: temperatura en celsius
    retorna: temperatura en fahrenheit*)
  double tempCel    
  tempCel <- (grados * (9.0 / 5)) + 32
  RETORNA tempCel
FIN MÓDULO celsiusToFahrenheit

MÓDULO fahrenheitToCelsius(REAL grados) RETORNA REAL
  (*convierte de escala Fahrenheit a Celsius
        grados: temperatura en fahrenheit
        retorna: temperatura en celsius*)
  REAL tempFah    
  tempFah <- (grados - 32) * (5.0 / 9)
  RETORNA tempFah
FIN MÓDULO fahrenheitToCelsius  
  

ALGORITMO calcularTemperatura() RETORNA ∅
(* este alg. Convierte una temperatura expresada 
en grados Fahrenheit a Grados celsius*) 
REAL tempIngresada, tempConvertida
CARACTER temp
ESCRIBIR("Conversión de temperaturas")
ESCRIBIR("--------------------------")
ESCRIBIR("¿Desea ingresar una 
      temp en Fahrenheit (F) ó Celsius (C)?: ")
LEER(temp)
ESCRIBIR("Ingrese la temperatura")
LEER(tempIngresada)
        
SI (temp = 'C' OR temp = 'c') ENTONCES
   tempConvertida <- 
      celsiusToFahrenheit(tempIngresada)
   ESCRIBIR(tempIngresada 
           + "grados Celsius, es equivante a: " 
           +tempConvertida+" grados Fahrenheit")
SINO
   SI (temp = 'F' OR temp = 'f') ENTONCES
      tempConvertida <-
      fahrenheitToCelsius(tempIngresada)
      ESCRIBIR(tempIngresada 
         + "grados Fahrenheit, es equivante a: " 
         +tempConvertida+" grados Celsius")
   FIN SI
FIN SI
FIN ALGORITMO calcularTemperatura 
import java.util.Scanner;

public class ConvertirTemp {
public static double celsiusToFahrenheit(double grados){
  double tempCel;    
  tempCel = (grados * (9.0 / 5)) + 32;
  return tempCel;
  }
public static double fahrenheitToCelsius(double grados){
  double tempFah;    
  tempFah = (grados - 32) * (5.0 / 9);
  return tempFah;
}
public static void main(String[] args) {
/* este alg. Convierte una temperatura expresada 
en grados Fahrenheit a Grados celsius*/ 
double tempIngresada, tempConvertida;
char temp;
Scanner sc = new Scanner(System.in);
System.out.println("Conversión de temperaturas");
System.out.println("¿Desea ingresar una 
      temp en Fahrenheit (F) ó Celsius (C)?: ");
temp = sc.next().charAt(0);
System.out.println("Ingrese la temperatura");
tempIngresada = sc.nextDouble();
        
if (temp == 'C' || temp == 'c') {
   tempConvertida = 
      celsiusToFahrenheit(tempIngresada);
   System.out.println(tempIngresada 
           + "° Celsius, es equivante a: " 
           +tempConvertida+"° Fahrenheit");
   }
else
  {if (temp == 'F' || temp == 'f') {
  tempConvertida = 
      fahrenheitToCelsius(tempIngresada);
  System.out.println(tempIngresada 
         + "grados Fahrenheit, es equivante a: " 
         +tempConvertida+" grados Celsius");
  }
  }
}
}

Descargar Archivo ConvertirTemp.java

Traza del algoritmo suponiendo que el usuario desea convertir 30 grados Celsius a Fahrenheit.

Algoritmo Principal:

tempIngresada tempConvertida temp Salida
30 86 ‘C’ Conversion de temperaturas
. ¿Desea ingresar una Temp en Fahrenheit (F) o Celsius (C)?
. 30° Celsius,equivante a: 86° Fahrenheit

celsiusToFahrenheit:

grados tempCel valor retornado
30 86 86

2.5 Áreas de Figuras Geométricas

Problema: Solicitar al usuario una figura geométrica: cuadrado, rectángulo ó circulo, solicitar los datos de la figura y calcular el área de la misma.

MÓDULO areaCuadrado(REAL lado) RETORNA REAL
  (* Obtiene el area de un cuadrado 
           lado: lado del cuadrado 
           retorna area del cuadrado *)
  REAL area
  area <- lado * lado
  RETORNA area
FIN MÓDULO areaCuadrado
    

MÓDULO areaRectangulo(REAL ladoMayor, 
                      REAL ladoMenor) RETORNA REAL
  (* Obtiene el área de un rectangulo
        ladoMayor: lado mayor del cuadrado
        ladoMenor: lado menor del cuadrado*)
        retorna el area del rectángulo *)
  REAL area
  area <- ladoMayor * ladoMenor
  RETORNA areaRectangulo

MÓDULO areaCirculo() RETORNA REAL
  (* Obtiene el área de un círculo
  radioCirculo: radio del círculo
  Retorna area del círculo  *)
  REAL area, PI
  PI <-3,1415
  area <- PI * potencia(radioCirculo,2)
  RETORNA area
FIN MÓDULO areaCirculo

ALGORITMO areas() RETORNA ∅
(* Calcula areas de distintas figuras geométricas *)
CARACTER figura
REAL lado1, lado2, radio, lado, 
      areaFigura, areaCalculada
ESCRIBIR("Indique la figura geométrica para calcular su área")
ESCRIBIR("Cuadrado (C), Rectángulo (R), Circulo (I):")
LEER(figura)
SEGUN (figura) HACER:
    'C': 
       ESCRIBIR("Ingrese el lado")
       LEER(lado)
       areaCalculada <- areaCuadrado(lado)
    'R': 
       ESCRIBIR("Ingrese el lado Mayor")
       LEER(lado1)
       ESCRIBIR("Ingrese el lado Menor")
       ESCRIBIR(lado2)
       areaCalculada <- areaRectangulo(lado1,lado2)
    'I': 
       ESCRIBIR("Ingrese el radio")
       LEER(radio)
       areaCalculada <- areaCuadrado(radio)
FIN SEGÚN
ESCRIBIR("La área de la figura es" + areaCalculada)
FIN ALGORITMO areas
import java.util.Scanner;

public class Areas {
public static double areaCuadrado(double lado){
  /* calcula el área de un cuadrado 
  lado: lado del cuadrado 
  retorna area del cuadrado*/
  double area;    
  area = lado * lado;
  return area;
}
public static double areaRectangulo(double ladoMayor, double ladoMenor){
  /* calcula el área de un rectángulo
  ladoMayor: lado mayor del cuadrado
  ladoMenor: lado menor del cuadrado*)
  retorna el area del rectángulo   */
  double area;    
  area= ladoMayor*ladoMenor;
  return area;
}  
public static double areaCirculo(double radioCirculo){
  /* calcula el área de un círculo
  radioCirculo: radio del círculo
  Retorna area del círculo  */
  double area;    
  area= Math.PI * Math.pow(radioCirculo,2);
  return area;
}
    
    
public static void main(String[] args) {
// este alg. calcula áreas de figuras geométricas
Scanner sc = new Scanner(System.in);
char figura;
double lado1, lado2, radio, lado, areaCalculada=1.0;
System.out.println(" Indique la figura geométrica para calcular su área");
System.out.println(" Cuadrado (C), Rectángulo (R) y Circulo (I):");
figura = sc.next().charAt(0);
switch (figura) {
    case 'C': 
       System.out.println("Ingrese el lado");
       lado = sc.nextDouble();
       areaCalculada = areaCuadrado(lado);
       break;
    case 'R': 
       System.out.println("Ingrese el lado Mayor");
       lado1 = sc.nextDouble();
       System.out.println("Ingrese el lado Menor");
       lado2 = sc.nextDouble();
       areaCalculada = areaRectangulo(lado1,lado2);
       break;
    case 'I': 
       System.out.println("Ingrese el radio");
       radio = sc.nextDouble();
       areaCalculada = areaCirculo(radio);
       break;
        }
System.out.println("El área de la figura es"
      +areaCalculada);
    
    }}

Traza del algoritmo suponiendo que el usuario desea calcular el area de un círculo de radio 2

Algoritmo Principal:

figura lado1 lado2 radio lado areaCalculada Salida
‘I’ 2,0 . 1.0 Indique la figura geométrica para calcular su área
. . 12,56 Cuadrado (C), Rectángulo (R) y Circulo (I):
. . Ingrese el radio
. . El área de la figura es 12,56

areaCirculo:

radioCirculo area valor retornado
2,0 12,56 12,56

Descargar Archivo Areas.java

2. Ejercicios Propuestos

Responder las siguientes preguntas:

  • En el ejercicio 2.2 sobre obtener el Dia de la Semana, indique:

    • ¿Cuál es la primitiva del algoritmo y cual es la instrucción java, en la cual se realiza la invocación?
    • ¿Cuál es el nombre del parámetro actual?
    • ¿Cuál es el nombre del parámetro formal?
  • Sabemos que hemos utilizado invocaciones o requerimientos a módulos (o métodos) cuando utilizamos la librería Math.

    -¿Cuántos parámetros actuales debemos utilizar al invocar al módulo Math.pow? -¿Es indistinto el orden de los parámetros?¿Porqué? -¿Podemos invocar al método pow utilizando caracteres?

    Luego, no debemos olvidar que al invocar a módulo o método es importante:

    1. Conocer el nombre del módulo y el objetivo del mismo
    2. Es importante tres cosas respecto a los parámetros que debemos enviarle:
      1. tener en cuenta la cantidad de parámetros
      2. el orden es importante
      3. la conformidad de tipos según la cadena de compatibilidad.
    3. Es importante entender qué retorna el método (si es que retorna un valor)

Para cada uno de los siguientes ejercicios especifique el pseudocódigo e implemente un programa en JAVA. No olvide incluir en cada módulo un comnentario que incluya: 1. objetivo del módulo, 2. el objetivo de cada parámetro y 3. el significado del valor retornado.

  • Construir un módulo esPar que reciba un número entero y retorne si el número es par o impar.

  • Construir un módulo esMayor que reciba dos números enteros y retorne el mayor de los números.

  • Construir un módulo esMayor que reciba tres números enteros y retorne el mayor de los números.

  • Construir un modulo esBisiesto que reciba un número entero que representa un año y determine si el año es bisiesto. Considere que el algoritmo para calcular si un año es bisiesto de acuerdo a las siguientes proposiciones o enunciados lógicos:

    • p: Es divisible entre 4
    • ¬q: No es divisible entre 100
    • r: Es divisible entre 400

    La fórmula lógica que se suele usar para establecer si un año es bisiesto sería cuando [p y ¬q] ó [r] es verdadera, pero esta otra p y [¬q ó r] sería más eficiente.

  • Construir un módulo que dado un caracter permita obtener la posición numérica de dicho caracter en la tabla UNICODE. Considere que la posición se determina a partir de un casting del valor char a entero.

  • Construir un módulo distanciaEntrePuntos para calcular la distancia entre dos pares de puntos (x,y) considerando la fórmula de Pitágoras: La distancia \(d\) entre \(p\)=(p1,p2) y \(q\)=(q1,q2) esta dada por \(d = \sqrt{(p_1 - q_1)^2 + (p_2 - q_2)^2}\)

  • Construir un algoritmo que haciendo uso de los módulos anteriores, solicite al usuarios tres pares de coordenadas (x,y) y permita obtener los dos pares de coordenadas (x,y) que tienen la menor distancia entre ellos.

  • Construir un algoritmo que le solicite al usuario el caracter que simboliza una operación (‘+’,‘-’,’*‘,’/’,), y dos operandos reales, y el algoritmo deberá evaluar el resultado de la operación con ambos operandos, respetando el orden en el cual son ingresados dichos operandos.