Está en la página 1de 31

Problema 1.

Escribir un programa para calcular el perímetro de


una circunferencia siguiendo el diálogo:
radio?__
perímetro=Nº

Solución 1. Con programa ad-hoc

class Programa{
static public void main(String[]args)
throws IOException
{
double r=U.readDouble(“radio?”);
U.println(“perímetro=” + 2*Math.PI*r);
}
}
Solución 2. Con clase para circunferencias
class Circunferencia{
private double r;
public Circunferencia(double x){
if(x<=0) U.abortar(“radio<=0”);
r=x;
}
public double perimetro(){
return 2*Math.PI*r;
}
}
class Programa{
static public void main(String[]args)
throws IOException{
Circunferencia c=new Circunferencia(
U.readDouble(“radio?”));
U.println(“perímetro=” + c.perimetro());
}
}
Problema 2. Calcular el área y el perímetro de un círculo

Solución 1. Modificar clase Circunferencia agregando método área

Solución 2. Usar (y escribir) nueva clase Circulo que:


 extienda la clase Circunferencia con método área
 herede las otras componentes (datos y métodos).

U.println(“Calcular área y perímetro de círculo”);

Circulo c=new Circulo(U.readDouble(“radio?”));

//uso de método de clase Circulo


U.println(“área=”+c.area());

//uso de método heredado de clase Circunferencia


U.println(“perímetro=”+c.perimetro());
//clase base o superior
class Circunferencia{
protected double r;//visible en clase y extensiones
public Circunferencia(double x){
r=x; if(r<=0) U.abortar(“radio<=0”);
}
public double perimetro(){
return 2*Math.PI*r;
}
}
//clase extendida o derivada
class Circulo extends Circunferencia{
public double area(){
return Math.PI*r*r;
}
public Circulo(double x){//constructor
super(x);//invocar ctor de clase superior
}
}
class Circulo extends Circunferencia

Circunferencia
perimetro
Circunferencia radio

Circulo
area
Circulo
Problema 3. Calcular área y perímetro de un círculo o un cuadrado

Circulo(1) o Cuadrado(2)? __
radio?__ o lado?__
area=Nº
perimetro=Nº

Programa:
int n=U.readInt(“Circulo(1) o Cuadrado(2)?”);
if(n==1){
Circulo c=new Circulo(U.readDouble(“radio?”));
U.println(“area=”+c.area());
U.println(“perimetro=”+c.perimetro());
}else if(n==2){
Cuadrado c=new Cuadrado(U.readDouble(“lado?”));
U.println(“area=”+c.area());
U.println(“perimetro=”+c.perimetro());
}else
U.abortar(“debe ser 1 o 2”);
Solución 1. Con clases independientes
class Circulo{
protected double r;
public Circulo(double x){
r=x; if(r<=0) U.abortar(“radio<=0”);
}
public double area(){return Math.PI*r*r;}
public double perimetro(){return 2*Math.PI*r;}
}
class Cuadrado{
protected double a;
public Cuadrado x){
a=x; if(a<=0) U.abortar(“lado<=0”);
}
public double area(){return a*a;}
public double perimetro(){return 4*a;}
}
Solución 2. Con jerarquía de clases
class Figura{
protected double x;
public Figura(double x){
this.x=x; if(x<=0) U.abortar(“<=0”);
}
}
class Circulo extends Figura{
public Circulo(double x){super(x);}
public double area(){return Math.PI*x*x;}
public double perimetro(){return 2*Math.PI*x;}
}
class Cuadrado extends Figura{
public Cuadrado(double x){super(x);}
public double area(){return x*x;}
public double perimetro(){return 4*x;}
}
Solución 3. Con métodos ficticios (redefinidos en extensiones)
class Figura{
protected double x;
public Figura(double x){
this.x=x; if(x<=0) U.abortar(“<=0”);
}
public double area(){return 0;}
public double perimetro(){return 0;}
}

Corolario. Programa usuario más breve


Figura f;
switch( U.readInt(“Circulo(1) o Cuadrado(2)?”) ){
case 1: f=new Circulo(U.readDouble(“radio?”)); break;
case 2: f=new Cuadrado(U.readDouble(“lado?”)); break;
default: U.abortar(“1 o 2”);
}
U.println(“area=”+f.area());
U.println(“perimetro=”+f.perimetro());
Enlace Dinámico (dynamic binding)

f=new Circulo(…); f=new Cuadrado(…);


 referencia a objeto de clase Figura puede apuntar también a objetos de
clase extendidas Circulo y Cuadrado
 objeto de clase extendida es un objeto de clase base (círculos y
cuadrados son figuras)

f.area()
si f apunta a un objeto de clase
 Cuadrado, se invoca método area de clase Cuadrado
 Circulo , se invoca método area de clase Circulo

x objeto clase
Cuadrado
f
referencia clase x objeto clase
Figura Circulo
Solución 4: Con clase abstracta que obliga a redefinir métodos

abstract class Figura{


protected double x;
public Figura(double x){
this.x=x; if(x<=0) U.abortar(“debe ser >0”);
}
abstract public double area();
abstract public double perimetro();
}
Notas
•no permite crear objetos, no admite new Figura()
•debe tener al menos un método abstracto:
abstract encabezamiento;
•obliga a clases extendidas a redefinir métodos abstractos
•permite definir otras figuras
class Rectangulo extends Figura{
protected double y;
public Rectangulo(double x,double y){
super(x); this.y=y; if(y<=0) U.abortar(“<=0”);
}
public double area(){return x*y;}
public double perimetro(){return 2*(x+y);}
}
class Triangulo extends Figura{
protected double y,z;
public Triangulo(double x,double y,double z){
super(x); this.y=y; this.z=z;
if(y<=0 || z<=0 || x+y<=z || x+z<=y || y+z<=x)
U.abortar(“no forman triangulo”);
}
public double perimetro(){return x+y+z;}
public double area(){
double s=(x+y+z)/2;
return Math.sqrt(s*(s-x)*(s-y)*(s-z));
}}
Problema . Escriba la clase abstracta Cuerpo y las clases extendidas Cubo, Esfera y
Caja para el siguiente programa que permite calcular el volumen y el área de un
cubo, una esfera, o una caja (paralelepípedo)
Cuerpo c;
switch(U.readInt(“Cubo(1),Esfera(2),o Caja(3)?”))
{
case 1: c=new Cubo(U.readDouble(“lado?”));
break;
case 2: c=new Esfera(U.readDouble(“radio?”));
break;
case 3: c=new Caja(U.readDouble(“largo?”),
U.readDouble(“ancho?”),
U.readDouble(“alto?”));
break;
default: U.abortar(“1, 2 o 3”);
}
U.println(“volumen=” + c.volumen());
U.println(“area=” + c.area());
Nota. El área de la esfera es 4r2 y el volumen es 4/3r3
abstract class Cuerpo{
protected double x;
public Cuerpo(double x){
this.x=x; if(x<=0) U.abortar(“<=0”);
}
abstract double area();
abstract double volumen();
}
class Esfera extends Cuerpo{
public Esfera(double x){super(x);}
public double area(){return 4*Math.PI*x*x;}
public double volumen(){return Math.PI*x*x*x*4/3;}
}
class Cubo extends Cuerpo{
public Cubo(double x){super(x);}
public double area(){return 6*x*x;}
public double volumen(){return x*x*x;}
}
class Caja extends Cuerpo{
protected double y, z;
public Caja(double x,double y,double z){
super(x); this.y=y; this.z=z;
if(y<=0 || z<=0) U.abortar(“<=0”);
}
public double area(){
return 2*(x*y + x*z + y*z);
}
public double volumen(){
return x*y*z;
}
}

Nota. Un cubo es también una caja


class Cubo extends Caja{
public Cubo(double x){super(x,x,x);}
}
Solución 2. Con interface
 clase base abstracta
 sólo con métodos implicitamente abstractos
 sin datos

interface Cuerpo
{
public double area();
public double volumen();
}
class Esfera implements Cuerpo{
protected double r;
public Esfera(double x){r=x;}
public double area(){
return 4*Math.PI*r*r;
}
public double volumen(){
return Math.PI*r*r*r*4/3;
}
}
class Cubo implements Cuerpo{
protected double a;
public Cubo(double x){a=x;}
public double area(){return 6*a*a;}
public double volumen(){return a*a*a;}
}
class Caja implements Cuerpo{
protected double l,a,h;//largo, ancho y altura
public Caja(double x,double y,double z){
l=x; a=y; h=z;
if(x<=0 || y<=0 || z<=0) U.abortar(“<=0”);
}
public double area(){
return 2*(l*a + l*h + a*h);
}
public double volumen(){
return l*a*h;
}
}

Nota. Un cubo es también una caja


class Cubo extends Caja{
public Cubo(double x){super(x,x,x);}
}
Object: clase raíz de toda la jerarquía de herencia de Java

class Object
{
//entrega la dir del objeto en memoria
//en la forma “NombreClase@nºhexadecimal” (base 16)
public String toString(){
return ...;
}
//entrega true sólo si es el mismo objeto
public boolean equals(Object x){
return this==x;//compara referencias
}
...//otros métodos
}
Toda clase extiende (implícita o explicitamente) a Object

class Fraccion extends Object{


protected int a, b;
...
//redefinición de métodos de clase Object
public String toString(){
return a+”/”+b;
}
public boolean equals(Object x){
Fraccion f=(Fraccion)x; //casting
return a*f.b == b*f.a;//compara objetos
}
}
 casting para considerar x como Fraccion
 error si x no es de clase Fraccion (o extensión)
Métodos genéricos (aplicables a objetos de distintas clases)
//invertir n objetos de arreglo x
static public void invertir(Object[]x,int n){
for(int i=0; i<n/2; ++i)
intercambiar(x,i,n-i-1);
}
//intercambiar x[i] con x[j]
static public void intercambiar(Object[]x,int i,int j){
Object aux=x[i]; x[i]=x[j]; x[j]=aux;
}
//mostrar un arreglo de objetos
static public void mostrar(Object[]x){
for(int i=0; i<x.length; ++i)
U.println(x[i].toString());
}
 si toString no existe en clase de x[i], se hereda de clase Object
 se puede escribir sólo U.println(x[i]);
Uso de métodos genéricos

//para arreglo de strings


String[]s={“C”,”B”,”A”,”B”,”C”};
mostrar(s);invertir(s,s.length);mostrar(s);

//para arreglo de fracciones


Fraccion[]f={new Fraccion(),
new Fraccion(1,2),
new Fraccion(“123/4567”),
new Fraccion(5)};
mostrar(f);invertir(f,f.length);mostrar(f);

//para arreglo heterogeneo


Object[]a={“A”,new Fraccion(1/2),”B”};
mostrar(a);invertir(a,a.length);mostrar(a);
Búsqueda (de un objeto en un arreglo de objetos)

//buscar objeto x en arreglo y de n objetos


//entregar índice de 1ªaparición (–1 si no está)
static public
int indice(Object x,Object[]y,int n){
for(int i=0; i<n; ++i)
if(y[i].equals(x)) return i;
return –1;
}
Uso
indice(“A”,s,s.length) entrega 2

indice(new Fraccion(2,4),f,f.length)
entrega 1 puesto que f[1] es new Fraccion(1,2)

indice(“A”,a,a.length) entrega 0
Comparable: Interface predefinida para clases que admiten comparar
objetos

interface Comparable{
public int compareTo(Object x);
}
class Fraccion implements Comparable{
...
//redefinición de compareTo de Comparable
public int compareTo(Object x){
Fraccion f=(Fraccion)x;
return a*f.b – b*f.a;
}
}
Nota
 clase String extiende Object e implementa Comparable
Problema. Ordenar un arreglo de n objetos (comparables)

encabezamiento
static public void ordenar(Comparable[]x,int n)

Invocación (ejemplos)
String[]s={...}; Fraccion[]f={...};
ordenar(s,s.length); ordenar(f,f.length);

Situación inicial: arreglo desordenado

Situación final: arreglo ordenado


Solución 1. Algoritmo de selección y reemplazo/intercambio

Repetir n veces
 seleccionar el menor
 intercambiar menor con el primero

¿situación intermedia (invariante)?

ip im
ip: índice del primero (de los que aún están desordenados)

im: índice del menor (entre los desordenados)

Si se intercambia x[ip] con x[im] y se avanza ip,


entonces la invariante se restablece (mantiene)
static public void ordenar(Comparable[]x,int n){
//repetir n veces
for(int ip=0; ip<n; ++ip)//para ip=0,...,n-1
{
//seleccionar el (indice del) menor
int im=ip;
for(int i=ip+1; i<n; ++i)
if(x[i].compareTo(x[im])<0) im=i;

//intercambiar menor con el primero


intercambiar(x,im,ip);
}
}
Algoritmo O(n2)
 las n iteraciones realizan n-1, n-2, ..., 1 comparaciones
 total de comparaciones: i, para i=1,...,n-1=n(n-1)/2=n2/2 - n/2
 orden de magnitud: n2
 ej, si n=100, se realizan del orden de 10.000 comparaciones
Búsqueda secuencial para arreglo ordenado:
O(n), pero peor caso realiza en promedio n/2 (y no n) comparaciones
int indice(Comparable x,Comparable[]y,int ip,int iu){
//recorrer todos los índices (de 1º a último)
for(int i=ip; i<=iu; ++i){
//si y[i]=x, devolver índice i
int c=y[i].compareTo(x);
if(c==0) return i;
//si y[i]>x, no está (pq y está ordenado)
if(c>0) break;
}
return –1;
}
recursivamente
if(ip>iu) return –1;
int c=y[ip].compareTo(x);
if(c==0) return ip;
return c>0? -1: indice(x,y,ip+1,iu);
Problema. Programar el algoritmo de búsqueda binaria
(para buscar eficientemente en arreglo ordenado)
encabezamiento
static public int indice(
Comparable x,Comparable[]y,int ip,int iu)

¿algoritmo?
Comparar x con elemento que está en la mitad del arreglo y
 Si son iguales, devolver índice de mitad
 Si x es menor, buscar en primera mitad del arreglo
(descartando segunda mitad)
 Si x es mayor, buscar en segunda mitad del arreglo
(descartando primera mitad)

Repetir mientras queden elementos.


Devolver –1 si x no está en arreglo y.
static public int indice
(Comparable x,Comparable[]y,int ip,int iu){
//repetir mientras queden elementos
while(ip<=iu){
//comparar x con elemento que está en la mitad
int im=(ip+iu)/2; //indice del medio
int c=x.compareTo(y[im]);
//si son iguales, devolver índice de mitad
if(c==0) return im;
//si x es menor, buscar en 1ª mitad del arreglo
if(c<0)
iu=im–1;//”subir” índice del último
//si x es mayor, buscar en 2ª mitad del arreglo
else
ip=im+1;//”bajar” índice del primero
}
//devolver –1 si x no está en arreglo y.
return –1;
}
Ejemplo de uso:

static public void main(String[]args){


String[]mes={“abril”,...,”septiembre”};
String[]month={“april”,..., “september”};

int i=indice(args[0],mes,0,mes.length-1);

U.println(
i<0? “mes incorrecto”: month[i]);
}
invocación
java TraducirMes mayo
may
java TraducirMes martes
mes incorrecto

También podría gustarte