miércoles, 31 de agosto de 2011

Ejercicio función invertir

Implementa la siguiente función, utilizando un objeto de la clase Stack.
  • Nombre y parámetros: List<Point> invertir (Iterator<Point> i , Point p)
  • Retorna: List<Point> (realmente será un objeto ArrayList<Point>)
  • Tarea: Crea un ArrayList de objetos Point que contenga los puntos obtenidos con el iterador pero en orden inverso, excluyendo los puntos que sean iguales al recibido en el segundo parámetro.
  • Si el segundo parámetro es null, se excluyen los puntos (0,0) 
  • Excepciones: IllegalArgumentException en caso de que el iterator no nos diera ni un solo Punto o bien fuese null.
Se añade el programa principal con el que se probó la función.

public class EjercicioStack {
    public static void main (String[] args) {
        Point a = new Point(0,0);
        Point b = new Point(1,1);
        Point c = new Point(2,2);
        Point d = null;
        ArrayList<Point> puntos = new ArrayList<Point>();
        ArrayList<Point> puntosInv;
        puntos.add(a);
        puntos.add(b);
        puntos.add(c);
        System.out.println(puntos);
        Iterator<Point> it = puntos.iterator();
        puntosInv = (ArrayList<Point>) invertir(it, d);
        System.out.println(puntosInv);
    }
    public static List<Point> invertir (Iterator<Point> i, Point p) {
        Stack<Point> pila = new Stack<Point>();
        ArrayList<Point> puntos = new ArrayList<Point>();
        Point aux;
        if (i == null || !i.hasNext()) {
            throw new IllegalArgumentException();
        }
        if (p == null) {
            p = new Point(0, 0);
        }
        while (i.hasNext()) {
            aux = i.next();
            if (!aux.equals(p))
                pila.push(aux);
        }
        while (!pila.empty()) {
            puntos.add(pila.pop());
        }
        return puntos;
    }
}

Ejercicio funciones insertar

Realizar las funciones:
  • int insertar (List<Comparable> l, Comparable d). La función recibe una lista de datos comparables, que debe estar ordenada, y un dato comparable que es el que se quiere insertar en la lista anterior. Como resultado se retorna la posición en la que ha sido insertado el dato.
  • void insertar (List<Comparable> l, Collection<Comparable> c). Recibe una lista de datos comparables, que estarán ordenados, y una colección de datos que se insertarán en el lugar correspondiente de la lista anterior. No retorna nada.
Se añade el programa principal con el que se probó la función.

public class Insertar {
    public static void main (String[] args) {
        LinkedList<String> nombres = new LinkedList<String>();
        LinkedList<String> nombres2 = new LinkedList<String>();
        int pos;
        pos = insertar((List)nombres, "Juan");
        System.out.println(nombres);
        System.out.println(pos);
        pos = insertar((List)nombres, "Antonio");
        System.out.println(nombres);
        System.out.println(pos);
        pos = insertar((List)nombres, "Manuela");
        System.out.println(nombres);
        System.out.println(pos);
        nombres2.add("Julia");
        nombres2.add("Angel");
        nombres2.add("Carlos");
        nombres2.add("Verónica");
        insertar((List)nombres, (Collection)nombres2);
        System.out.println(nombres);
    }
    public static int insertar(List<Comparable> l, Comparable d) {
        int i=0;
        ListIterator<Comparable> it = l.listIterator();
        while (i < l.size() && d.compareTo(it.next()) > 0) {
            i++;
        }
        if (i < l.size())
            it.previous();
        it.add(d);
        return i;
    }
    public static void insertar(List<Comparable> l, Collection<Comparable> c) {
        Iterator<Comparable> itC = c.iterator();
        while (itC.hasNext()) {
            insertar(l, itC.next());
        }
    }
}

lunes, 29 de agosto de 2011

Ejercicio "ListaEnlazada"

Para conocer un poco mejor el funcionamiento de la clase LinkedList<T>, realizar el siguiente ejercicio:
  1. Crear un LinkedList de Integer: LinkedList<Integer>.
  2. Añadir los números del 1 al 5.
  3. Eliminar los números 2, 3 y 4.
    1. En primer lugar con la función remove (int index) propia de los objetos LinkedList.
    2. En segundo lugar, utilizando un objeto Iterator.
NOTA: se imprime en pantalla a menudo para comprobar que todo va funcionando bien en cada paso.

public class ListaEnlazada {
    public static void main (String[] args) {
        LinkedList<Integer> lista = new LinkedList<Integer>();
        int i, j=1;
        for (i=0; i<5; i++){
            lista.add(i+1);
        }
        System.out.println(lista.toString());
        for (i=0; i<3; i++){
            lista.remove(j);
        }
        System.out.println(lista.toString());
        lista.add(1, 2);
        lista.add(2, 3);
        lista.add(3, 4);
        System.out.println(lista.toString());
        Iterator<Integer> it = lista.iterator();
        it.next();
        it.next();
        for (i=0; i<2; i++){
            it.remove();
            it.next();
        }
        it.remove();
        System.out.println(lista.toString());
    }
}

Ejercicio "Conjunto"

Crear la clase Conjunto<T>, que implementará la interfaz Set<T>. No se pondrá código a todas las funciones de Set<T>, tan sólo aquellas que nos interesan de momento.
Para almacenar todos los objetos que forman parte del conjunto, se empleará un ArrayList. Además, se creará la clase privada ParaRecorrerMiConjunto, alojada dentro de la clase Conjunto<T>, que implementa Iterator<T> y nos permite recorrer todos los elementos que forman parte del conjunto.

public class Conjunto<T> implements Set<T> {
    private ArrayList<T> datos;
    private class ParaRecorrerMiConjunto implements Iterator<T> {
        private int actual = -1;
        public boolean hasNext() {
            return actual < datos.size() - 1;
        }
        public T next() {
            if (!hasNext()) {
                throw new java.util.NoSuchElementException();
            }
            actual++;
            return datos.get(actual);
        }
        public void remove() {
            throw new UnsupportedOperationException("Not supported yet.");
        }
    }
    public Conjunto() {
        datos = new ArrayList<T>();
    }
    public void clear() {
        datos.clear();
    }
    @SuppressWarnings("element-type-mismatch")
    public boolean contains(Object o) {
        return datos.contains(o);
    }
    public int size() {
        return datos.size();
    }
    public boolean isEmpty() {
        return datos.isEmpty();
    }
    public boolean add(T e) {
        if (!datos.contains(e)) {
            return datos.add(e);
        }
        return false;
    }
    @SuppressWarnings("element-type-mismatch")
    public boolean remove(Object o) {
        return datos.remove(o);
    }
    @Override
    public String toString() {
        return datos.toString();
    }
    @Override
    public boolean equals(Object o) throws ClassCastException {
        Conjunto<T> aux = (Conjunto<T>) o;
        return this.datos.containsAll(aux.datos) & aux.datos.containsAll(this.datos);
    }
    public Iterator<T> iterator() {
        return new ParaRecorrerMiConjunto();
    }
    public Object[] toArray() {
        throw new UnsupportedOperationException("Not supported yet.");
    }
    public Object[] toArray(Object[] a) {
        throw new UnsupportedOperationException("Not supported yet.");
    }
    public boolean containsAll(Collection c) {
        throw new UnsupportedOperationException("Not supported yet.");
    }
    public boolean addAll(Collection c) {
        throw new UnsupportedOperationException("Not supported yet.");
    }
    public boolean retainAll(Collection c) {
        throw new UnsupportedOperationException("Not supported yet.");
    }
    public boolean removeAll(Collection c) {
        throw new UnsupportedOperationException("Not supported yet.");
    }
}

MODIFICACIÓN
Para que funcione realmente como un conjunto de cosas, modificaremos la clase ParaRecorrerMiConjunto, de manera que cada vez que se instancie un iterador para recorrer los elementos del conjunto, lo haga en orden aleatorio.

public class Conjunto3<T> implements Set<T> {
    private ArrayList<T> datos;
    private class ParaRecorrerMiConjunto implements Iterator<T>{
        private int actual=-1;
        private ArrayList<T> aux;
        ParaRecorrerMiConjunto(){
            aux = new ArrayList<T>(datos);
            Collections.shuffle(aux);
        }
        public boolean hasNext() {
            return !aux.isEmpty();
        }
        public T next() {
            if(!hasNext())
                throw new java.util.NoSuchElementException();
            actual++;
            return aux.get(actual);
        }
        public void remove() {
            throw new UnsupportedOperationException("Not supported yet.");
        }
    }
    public Conjunto3() {
        datos = new ArrayList<T>();
    }
    public void clear() {
        datos.clear();
    }
    @SuppressWarnings("element-type-mismatch")
    public boolean contains(Object o) {
        return datos.contains(o);
    }
    public int size() {
        return datos.size();
    }
    public boolean isEmpty() {
        return datos.isEmpty();
    }
    public boolean add(T e) {
        if (!datos.contains(e)) {
            return datos.add(e);
        }
        return false;
    }
    @SuppressWarnings("element-type-mismatch")
    public boolean remove(Object o) {
        return datos.remove(o);
    }
    @Override
    public String toString() {
        return datos.toString();
    }
    @Override
    public boolean equals(Object o) throws ClassCastException {
        Conjunto3<T> aux = (Conjunto3<T>) o;
        return this.datos.containsAll(aux.datos) & aux.datos.containsAll(this.datos);
    }
    public Iterator<T> iterator() {
        return new ParaRecorrerMiConjunto();
    }
    public Object[] toArray() {
        throw new UnsupportedOperationException("Not supported yet.");
    }
    public Object[] toArray(Object[] a) {
        throw new UnsupportedOperationException("Not supported yet.");
    }
    public boolean containsAll(Collection c) {
        throw new UnsupportedOperationException("Not supported yet.");
    }
    public boolean addAll(Collection c) {
        throw new UnsupportedOperationException("Not supported yet.");
    }
    public boolean retainAll(Collection c) {
        throw new UnsupportedOperationException("Not supported yet.");
    }
    public boolean removeAll(Collection c) {
        throw new UnsupportedOperationException("Not supported yet.");
    }
}

sábado, 27 de agosto de 2011

Ejercicio "Fracción" (modificación)

Modificar la clase Fraccion, de manera que implemente las interfaces Comparable y Reseteable, es decir, debe poner código a las funciones de esas interfaces. Como las interfaces se encuentran en otro paquete distinto a la clase Fraccion, se deben importar.
Además, se creará la excepción FraccionException, que se lanzará en el constructor de la clase Fraccion cuando el denominador sea 0.

EXCEPCIÓN: FraccionException

public class FraccionException extends ArithmeticException {
    public FraccionException(){
    }
    public FraccionException(String mensaje){
        super(mensaje);
    }
}

Las excepciones se programan normalmente con dos constructores:
  • Uno por defecto, que no recibe nada.
  • Otro que recibe un String, con el texto que queremos que se muestre si se lanza esa excepción.
Las excepciones pueden heredar de las existentes en Java, siempre que tenga sentido que así sea. Si queremos que la excepción no sea marcada, heredará de RuntimeException o de alguna de las que están dentro de ese conjunto.

CLASE: Fraccion

import interfaces.Comparable;
import interfaces.Reseteable;

public class Fraccion implements Comparable, Reseteable {
    private int numerador;
    private int denominador;
    public Fraccion(int num){
        this(num, 1);
    }
    public Fraccion(int num, int den){
        if (den == 0)
            throw new FraccionException();
        numerador = num;
        denominador = den;
    }
    public Fraccion inversa() {
        Fraccion aux;
        aux = new Fraccion(denominador, numerador);
        return aux;
    }
    public Fraccion producto(Fraccion f) {
        Fraccion resultado;
        int numRes, denRes;
        numRes = f.numerador * numerador;
        denRes = f.denominador * denominador;
        resultado = new Fraccion(numRes, denRes);
        return resultado;
    }
    @Override
    public String toString() {
        return numerador+"/"+denominador;
    }
    public Fraccion opuesta() {
        Fraccion aux;
        aux = new Fraccion(-numerador, denominador);

        return aux;
    }
    public static int mcd(int num1, int num2) {
        int aux;
        //Algoritmo de Euclides
        while (num2 != 0){
            aux = num1;
            num1 = num2;
            num2 = aux % num2;
        }
        return num1;
    }
    public static int mcm(int num1, int num2) {
        int mcm;
        int a=num1, b=num2;

        while (num1 != num2){
            if (num1>num2)
                num1 = num1-num2;
            else
                num2 = num2-num1;
        }
        mcm = a*b/num2;
        return mcm;
    }
    public Fraccion suma(Fraccion f2) {
        Fraccion resultado;
        int minimo, num;
        minimo = mcm(denominador, f2.denominador);
        num = (minimo/denominador)*numerador + (minimo/f2.denominador)*f2.numerador;
        resultado = new Fraccion(num, minimo);
        return resultado;
    }
    public boolean equals(Fraccion f2) {
        return numerador==f2.numerador & denominador==f2.denominador;
    }
    public Fraccion simplificar() {
        int divisor;
        divisor = mcd(numerador, denominador);
        numerador = numerador/divisor;
        denominador = denominador/divisor;
        return this;
    }
    public int comparadoCon(Object obj) throws ClassCastException {
        Fraccion f2 = (Fraccion) obj;
        double prim, segun;
        int res;
        prim = numerador/(double)denominador;
        segun = f2.numerador/(double)f2.denominador;
        if (prim < segun)
            res = -1;
        else if (prim > segun)
            res = 1;
        else
            res = 0;
        return res;
    }
    public void reset() {
        numerador = 0;
        denominador = 1;
    }
}

Interfaces

Una interfaz (Java) es una colección de métodos, que no tendrán código, y de atributos, que serán públicos, estáticos y constantes. De esta manera, las clases que hereden de estás interfaces, se verán obligadas a ponerle código a las funciones, a no ser que se trate de clases abstractas.

Es en la documentación de la interfaz donde se especificará de forma concreta qué deben hacer los distintos métodos que la componen. Por ejemplo, la interfaz Comparable, de Java, contiene el método compareTo, que se define detalladamente aquí. Por lo tanto, si alguna clase implementa la interfaz Comparable, debe tener en cuenta la definición de su método para desarrollarlo de acuerdo con su fin.

Las interfaces pueden heredar de otras, en este caso se emplea "extends":

public class NombreInterface1 extends NombreInterface2 {
    //Aquí van los métodos y atributos de NombreInterface1
}

A continuación se muestran dos ejemplos de interfaces, que se utilizarán en algunos ejercicios realizados posteriormente:

public interface Comparable {
    int comparadoCon(Object obj) throws ClassCastException;
}

public interface Reseteable {
    void reset();
}

Cuando una clase hereda de una interfaz, es decir, cuando la implementa, se utiliza la palabra reservada "implements":

public class NombreClase implements NombreInterface {
    //Aquí va el código de NombreClase
}

Una clase puede implementar varias interfaces:

public class NombreClase implements NombreInterface1, NombreInterface2 {
    //Aquí va el código de NombreClase
}

REFERENCIAS:

Ejercicio "Dado" (modificación)

Modificar la clase Dado, añadiéndole varias funciones estáticas que se definen a continuación:
  • String lanzamientos (Dado d, int v). Lanza el dado "d" tantas veces como se le indique y retorna un String con los resultados de las tiradas.
  • int lanzamientos (Dado d1, Dado d2). Lanza los dos dados y devuelve la suma de las tiradas.
  • Dado[] factoria (int d, int c). Construye tantos dados como se le indique en "d" y con las caras indicadas en "c". Devuelve una tabla con los dados creados.
  • String[] lanzamientos (Dado[] t). Lanza cada uno de los dados de la tabla y los guarda en una tabla de String.
  • String[] lanzamientos (Dado[], int v). Lanza cada dado de la tabla el número de veces que se indica y se guardan las tiradas de cada dado en la misma casilla de la tabla de String.
public class Dado {
    protected int caras;
    public Dado(int lados) {
        caras = lados;
    }
    public int tirarDado() {
        int aux;
        aux = (int) (Math.random()*caras+1);
        return aux;
    }
    public static String lanzamientos(Dado d, int veces){
        StringBuffer aux = new StringBuffer("");
        int i;
        for(i=0; i<veces; i++)
            aux.append(d.tirarDado());
        return aux.toString();
    }
    public static int lanzamientos(Dado d1, Dado d2){
        return d1.tirarDado()+d2.tirarDado();
    }
    public static Dado[] factoria(int cuantos, int caras){
        Dado[] caja= new Dado[cuantos];
        int i;
        for (i=0; i<caras; i++)
            caja[i]=new Dado(caras);
        return caja;
    }
    public static String[] lanzamientos(Dado[] caja){
        int i;
        String[] res= new String[caja.length];
        for (i=0; i<caja.length; i++)
            res[i]=Integer.toString(caja[i].tirarDado());
        return res;
    }
    public static String[] lanzamientos(Dado[] caja, int veces){
        int i, j;
        String[] res= new String[caja.length];
        for (i=0; i<caja.length; i++){
            res[i]=Dado.lanzamientos(caja[i], veces);
        }
        return res;
    }
}

Crear ahora la clase DadoConMemoria, que herede de la anterior.

La clase DadoConMemoria funcionará de manera similar a la clase Dado, pero tendrá un historial en el que irá almacenando todas las tiradas realizadas.
Además, esta clase tendrá dos constructores:
  1. Un constructor por defecto, que construirá un dado con 6 caras.
  2. Un constructor que recibe el número de lados que tendrá el dado.
Se añadirán un atributo para guardar el historial de tiradas y las siguientes funciones:
  • void reset(). Borra la memoria.
  • Integer[] historico(). Retorna un listado de todos los valores obtenidos, desde la última tirada a la primera.
  • Integer[] historico(int n). Retorna un listado de los últimos "n" valores obtenidos.
Además, se modificarán las funciones heredadas si se cree necesario, para que funcione como debe, es decir, para almacenar el historial.

public class DadoConMemoria extends Dado {
    private ArrayList<Integer> historico=new ArrayList<Integer>();
    public DadoConMemoria() {
        this(6);
    }
    public DadoConMemoria(int lados) {
        super(lados);
    }
    @Override
    public int tirarDado() {
        int aux;
        aux = (int) (Math.random()*caras+1);
        historico.add(0, aux);
        return aux;
    }
    public void reset() {
        historico = null;
    }
    public Integer[] historico() {
        Integer[] aux = new Integer[0];
        aux=historico.toArray(aux);
        return aux;
    }
    public Integer[] historico(int ult) {
        Integer[] aux = new Integer[0];
        aux=historico.subList(0, ult).toArray(aux);
        return aux;
    }
}

Ejercicio clase "PuntoGordo"

Dada la clase PuntoPoli:

public class PuntoPoli {
    private int x, y;
    public PuntoPoli() {
        y = x = 30;
    }
    public PuntoPoli(int px, int py) {
        x = px;
        y = py;
    }
    public float distancia() {
        System.out.println("EJECUTANDO LA FUNCION DISTANCIA DE PuntoPoli");
        return (float) Math.sqrt(x * x + y * y);
    }
    public void izq(){
        x=x-1;
    }
    public void der(){
        x=x+1;
    }
    public void arr(){
        y=y-1;
    }
    public void aba(){
        y=y+1;
    }
}

Crear la clase PuntoGordo, que heredará de la anterior. Además de las coordenadas, se debe almacenar su diámetro y se modificarán las funciones de movimiento del punto, para que en el caso del PuntoGordo, en vez de moverse de uno en uno, se muevan el tamaño del diámetro.

public class PuntoGordo extends PuntoPoli{
    private int diametro;
    public PuntoGordo(int a, int b, int c) {
        super(a, b);
        diametro = c;
    }
    @Override
    public float distancia() {
        System.out.println("EJECUTANDO LA FUNCION DISTANCIA DE PuntoGordo");
        return super.distancia() - diametro / 2.0f;
    }
    @Override
    public void izq(){
        int i;
        for (i=0; i<diametro; i++)
            super.izq();
    }
    @Override
    public void der(){
        int i;
        for (i=0; i<diametro; i++)
            super.der();
    }
    @Override
    public void arr(){
        int i;
        for (i=0; i<diametro; i++)
            super.arr();
    }
    @Override
    public void aba(){
        int i;
        for (i=0; i<diametro; i++)
            super.aba();
    }
}

Ejercicio "Pila" con ArrayList

Crear la clase PilaString, que tendrá las siguientes funciones:
  • apilar. Recibe el objeto a colocar en la pila (un String).
  • desapilar. Elimina el último objeto de la pila y lo retorna como dato.
  • vacia. Retorna un boolean indicando si la pila está o no vacía.
Para almacenar los objetos se utilizará la clase ArrayList de Java. El atributo será privado para que no se pueda acceder a él directamente.

public class PilaString {
    private ArrayList<String> pila = new ArrayList<String>();
    public void apilar(String frase) {
        pila.add(frase);
    }
    public String desapilar() {
        return pila.remove(pila.size()-1);
    }
    public boolean vacia() {
        return pila.isEmpty();
    }
}

jueves, 25 de agosto de 2011

SyntaxHighlighter

Esta herramienta, basada en JavaScript, para mostrar código fuente correctamente resaltado, tal como si lo estuviésemos viendo en un IDE, me ha parecido de lo más útil para todos aquellos que tengáis un blog de programación o, simplemente, que queráis añadir entradas con código en alguna ocasión.

SyntaxHighlighter funciona con varios lenguajes de programación, como Java, PHP, Ruby, etc, etc, etc. En este enlace se pueden ver todos los "brushes" (ficheros que definen cómo se debe resaltar el código, en función del lenguaje): http://alexgorbatchev.com/SyntaxHighlighter/manual/brushes/

A continuación va un pequeño tutorial sobre cómo utilizar SyntaxHighlighter en Blogger:

1.- Ir a la pestaña de "Diseño" de vuestro blog.
2.- Hacer clic sobre "Edición de HTML".
3.- Dentro de la cabecera, es decir, entre las etiquetas <head> y </head> añadir lo siguiente:

<link href='http://alexgorbatchev.com/pub/sh/current/styles/shCore.css' rel='stylesheet' type='text/css'/>
<link href='http://alexgorbatchev.com/pub/sh/current/styles/shThemeDefault.css' rel='stylesheet' type='text/css'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shCore.js' type='text/javascript'/>
<!-- A CONTINUACIÓN, LOS "BRUSHES" -->
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushJScript.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushJava.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushXml.js' type='text/javascript'/>
<script type='text/javascript'>
    SyntaxHighlighter.config.bloggerMode = true;
    SyntaxHighlighter.all();
</script>

Con esto "instalamos" SyntaxHighlighter en el blog y también se añaden los diferentes "brushes", según los lenguajes de programación que se van a utilizar en el blog (se pueden añadir posteriormente si vamos a poner algo en otro lenguaje). En mi caso he puesto para Java, JavaScript y HTML.


4.- Finalmente hacemos clic en "GUARDAR PLANTILLA" y ya podemos crear o editar nuestras entradas con código para darle otro aire al blog.
5.- Al editar entradas...
  • Debemos ir a "Edición de HTML".
  • Allí añadimos las etiquetas:
<pre class="brush: java">
    <!-- AQUÍ VA EL CÓDIGO -->
</pre>
  • Y entre las etiquetas copiamos el código que queremos mostrar.
  • Cambiaremos "brush: java", según el lenguaje que vayamos a utilizar. Por ejemplo, parte del texto de esta entrada (con "brush: xml"):

REFERENCIAS:
NOTA:
Durante el tiempo que llevo utilizando SyntaxHighlighter, me ha dado algunos problemas, a veces, con los bucles (for y while) en Java, pero de resto todo ha ido genial y da un aspecto más claro y legible al blog.
Para resolver estos problemas con bucles, lo que he hecho ha sido borrar en "Edición de HTML" el código que modificaba el SyntaxHighlighter y después, en "Redactar" volver a copiar el código que falta (es decir, a partir del bucle).
Espero que se entienda, si no, para eso estoy aquí :)