Calcular determinante de una matriz

Aprovechando que he tenido un poco de tiempo libre mientras trabajaba, he aprovechado para hacer un programilla en Java, para que no se me vaya olvidando el lenguaje.

Esto es una aplicación que crea una matriz de tamanno x tamanno (en este ejemplo, he puesto 6x6), y calcula su respectivo determinante a base de llamar a un algoritmo recursivo que se va llamando a si mismo hasta llegar a una matriz de 2x2.

Dejo el código fuente.

Determinante.java
class Determinante
{
 public static void main(String args[])
 {
  int tamanno = 6, i, j;
  int matriz[][] = new int[tamanno][tamanno];
  for (i=0;i<tamanno;i++)
  {
   for (j=0;j<tamanno;j++)
   {
    matriz[i][j] = (int)(Math.random()*10)-5;
   }
  }

  printmat(matriz);

  System.out.println(determin(matriz));
 }

 public static void printmat(int matriz[][])
 {
  int i, j;
  for (i=0;i<matriz.length;i++)
  {
   for (j=0;j<matriz.length;j++)
    System.out.print(String.valueOf(matriz[i][j]) + "\t");
   System.out.println();
  }
  System.out.println();
 }

 public static int[][] submatrize(int matriz[][], int x, int y)
 {
  int submatriz[][] = new int[matriz.length-1][matriz.length-1];
  int i, j, cur_x=0, cur_y=0;
  for (i=0;i<matriz.length;i++)
  {
   if (i != x)
   {
    cur_y=0;
    for (j=0;j<matriz.length;j++)
    {
     if (j != y)
     {
      submatriz[cur_x][cur_y] = matriz[i][j];
      cur_y++;
     }
    }
    cur_x++;
   }
  }
  return submatriz;
 }

 public static int determin(int matriz[][])
 {
  int deter=0;
  int i, mult = 1;
  if (matriz.length > 2)
  {
   for (i=0;i<matriz.length;i++)
   {
    deter += mult * matriz[i][0] * determin(submatrize(matriz,i,0));
    mult *= -1;
   }
   return deter;
  }else
   return matriz[0][0] * matriz[1][1] - matriz[0][1] * matriz[1][0];
 }
}

Resultados:
5x5
run:
-3        -4        -1        -4        -5        1        
-2        -5        -4        1        -4        -3        
0        0        -3        -3        2        -4        
1        1        0        -4        -3        0        
4        -2        -3        -4        2        2        
0        3        -2        4        3        -4        

9756
BUILD SUCCESSFUL (total time: 0 seconds)

10x10
run:
-5        -3        0        -2        4        -5        0        -2        3        -5        
1        3        -3        1        2        2        -1        0        -4        -4        
-5        -5        3        0        1        -4        3        4        -1        2        
-1        2        -4        -1        4        -2        -3        3        -2        2        
1        -3        -1        1        -1        -2        -4        1        0        1        
2        2        1        1        3        1        3        -5        -4        -1        
3        -3        -4        1        -3        4        1        4        -2        -2        
-5        -5        2        -5        1        -1        1        -3        -5        3        
1        -4        -4        2        -5        -5        1        4        3        4        
0        -5        -3        -5        2        1        -1        -1        -3        -4        

71736511
BUILD SUCCESSFUL (total time: 2 seconds)

A partir de ahi los tiempos de ejecución se disparan

Inactividad temporal

Por una vez que me animo a crear un blog, y a las dos semanas me surge un trabajillo con el que no tendre tiempo para seguir aprendiendo Java, ni para atender al blog (mientras que la temática principal siga siendo Java). Me da bastante rabia que, ahora que parecía estar acomodándome a este lenguaje, tenga que volver a dejarlo de lado. Espero estar de vuelta con Java lo antes posible.

Siguiendo con AWT

Despues de pasarme siguiendo el tutorial que especifiqué en Empezando con AWT, y viendo lo poco que me entero de todo el código que va apareciendo y demás, voy a probar a aprender de los códigos que Casidiablo tiene puestos en su apartado de Java.

He adaptado los códigos de los ejemplos de [GUIs de Java]. He vuelto a hacer la misma aplicación que en Primera aplicación con AWT, el de calcular el máximo común divisor, pero esta vez, en caso de que no se introduzcan números enteros en los campos de texto, no da error.


PruebaJFrame.java
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class PruebaJFrame extends JFrame {
    private int ancho = 300, alto = 170, altofila = 25;
    Dimension entero, medio, tercio, cuarto;
   private JLabel etiqueta1, etiqueta2, etiqueta3;
   private JTextField numero1, numero2;
   private JButton mcdCalc;

   // configurar GUI
   public PruebaJFrame()
   {
      super( "Calcular mcd" );
      entero = new Dimension(ancho, altofila);
      medio = new Dimension((int)Math.floor(ancho / 2),altofila);
      tercio = new Dimension((int)Math.floor(ancho / 3),altofila);
      cuarto = new Dimension((int)Math.floor(ancho / 4),altofila);
      this.setResizable(false);

      // obtener panel de contenido y establecer su esquema
      Container contenedor = getContentPane();
      contenedor.setLayout( new FlowLayout() );

      etiqueta1 = new JLabel("Introduce un número: ");
      etiqueta1.setPreferredSize(medio);
      contenedor.add(etiqueta1);
      numero1 = new JTextField(5);
      numero1.setPreferredSize(medio);
      contenedor.add(numero1);
      etiqueta2 = new JLabel("Introduce un número: ");
      etiqueta2.setPreferredSize(medio);
      contenedor.add(etiqueta2);
      numero2 = new JTextField(5);
      numero2.setPreferredSize(medio);
      contenedor.add(numero2);
      mcdCalc = new JButton("Calcular mcd");
      mcdCalc.setPreferredSize(medio);
      contenedor.add(mcdCalc);
      ManejadorMCD manejarmcd = new ManejadorMCD();
      etiqueta3 = new JLabel("",JLabel.CENTER);
      etiqueta3.setPreferredSize(entero);
      contenedor.add(etiqueta3);
      mcdCalc.addActionListener(manejarmcd);


      setSize( ancho, alto );
      setVisible( true );

   } // fin del constructor

   public static void main( String args[] )
   {
      JFrame.setDefaultLookAndFeelDecorated(true);
      PruebaJFrame aplicacion = new PruebaJFrame();
      aplicacion.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
   }

   private class ManejadorMCD implements ActionListener
   {
       public void actionPerformed(ActionEvent evento)
       {
           try
           {
               etiqueta3.setText(String.valueOf(mcd(Integer.parseInt(numero1.getText()), Integer.parseInt(numero2.getText()))));
           } catch (NumberFormatException e)
           {
               etiqueta3.setText("Introduzca números enteros, por favor");
           }
       }
   }

   private int mcd(int x, int y)
    {
       if (x % y == 0)
           return y;
       else
           return mcd(y, x % y);
   }
}

El resulstado:

Reparto invitaciones a Diaspora

Mediante el blog de Alejandro (BASHYC), he conseguido una invitacion a esta nueva red social libre llamada Diaspora. De momento, voy a dejar para mañana el indagar por sus funcionalidades, opciones y posibilidades.

El que necesite invitaciones, puede pedirlos aquí mismamente. Tengo habilitada la moderación de comentarios, por lo que podeis poner los e-mails, que no los pienso publicar ;-)

Primera aplicación con AWT

En momentos como este, hecho de menos la época en la que empecé a programar con Visual Basic. Todo era tan fácil... arrastrar campos de texto, hacer doble click en los botones, seleccionar eventos, escribir 3 lineas, y todo funcionaba. En cambio, es mirar lo que he tenido que hacer en Java para escribir un programa super cutre que no hace más que calcular el máximo común divisor, y se me cae el mundo encima. No dudo que haya formas más fáciles de hacerlo, de hecho, ni me he puesto a indagar entre las opciones que puede brindar NetBeans para la realización de interfaces. Lo que he hecho no es más que seguir un tutorial, que tiene pinta de estar bastante anticuado, e ir metiendo modificaciones y un poco de freestyle, pero por lo menos funciona correctamente, siempre que se metan valores válidos en los campos de texto. Próximamente, ya volveré a tocar este código para que funcione bien aunque no se metan valores válidos.

import java.awt.*;

public class AppAWT extends Frame {
    static final int ANCHO = 200;
    static final int ALTO  = 200;
    Dimension filas;
    Label eti1, eti2, lblmcd;
    TextField num1, num2;
    Button calc;

    public AppAWT()
    {
        super("Primera prueba con AWT"); //Ponerle un título a la ventana
        filas = new Dimension(ANCHO,30);
        setLayout(new FlowLayout());
        eti1 = new Label("Numero 1: ");
        num1 = new TextField(4);
        eti2 = new Label("Numero 2: ");
        num2 = new TextField(4);
        calc = new Button("Calcular mcd");
        lblmcd = new Label("",Label.CENTER);
        lblmcd.setPreferredSize(filas);
        Panel fila1 = new Panel();
        fila1.setPreferredSize(filas);
        fila1.add(eti1);
        fila1.add(num1);
        add(fila1);
        Panel fila2 = new Panel();
        fila2.setPreferredSize(filas);
        fila2.add(eti2);
        fila2.add(num2);
        add(fila2);
        Panel fila3 = new Panel();
        fila3.setPreferredSize(filas);
        fila3.add(calc);
        add(fila3);
        Panel fila4 = new Panel();
        fila4.setPreferredSize(filas);
        fila4.add(lblmcd);
        add(fila4);
        pack();
        resize(ANCHO,ALTO);
        show();
    }

    public boolean handleEvent(Event evt)
    {
        if (evt.id == Event.WINDOW_DESTROY)
        {
            System.exit(0);
            return true;
        }
        if (evt.target instanceof Button)
        {
            lblmcd.setText(String.valueOf(mcd(Integer.parseInt(num1.getText()),Integer.parseInt(num2.getText()))));
        }
        return false;
    }

    public static void main(String args[])
    {
        new AppAWT();
    }

    public int mcd(int x, int y)
    {
        if (x % y == 0)
            return y;
        else
            return mcd(y, x % y);
    }
}

Empezando con AWT

Después de probar lo básico de los applets, voy a meter mano a AWT (Abstract Window Toolkit, Herramientas de Ventanas Abstractas), que viene a ser una forma de hacer interfaces compatible con los Applets (según lo que he podido leer hasta ahora). El tutorial que voy a seguir va a ser el siguiente: http://sunsite.dcc.uchile.cl/java/docs/JavaTut/Intro/tabla.html#awt

Espero que el tutorial no esté un poco desfasado. Me refiero a que, a medida que he ido leyendo, el tutorial, he podido ver como hacía mención a Windows 95 y puede que el tutorial esté un poco anticuado y las cosas hayan cambiado un poquitín. Si esto último no supone ningún dolor de cabeza, la cosa debería ir bien.

Mejor lo dejo para mañana, que ahora ya no son horas para ponerse a currar

Applet que dibuja un elipse a base de lineas

Un applet que dibuja un elipse a base de lineas dibujadas cada 15º (PI / 12 en radianes), de la altura y anchura que se le pasan por parámetros. Cutre, pero funciona :D De momento me sirve para mantener la moral alta.

Codigo del HTML
<html>
<head>
<title>Java Applet</title>
</head>

<body>
<applet code="Elipse.class" height="100" width="300">
 <param name="altura" value="100" />
    <param name="anchura" value="300" />
</applet>
</body>
</html>

Codigo del archivo Elipse.java
import java.awt.Graphics;
import javax.swing.JApplet;
public class Elipse extends JApplet
{
    public void paint( Graphics g )
    {
        super.paint( g );
        final int altura = Integer.parseInt(getParameter("altura"));
        final int anchura = Integer.parseInt(getParameter("anchura"));
        double punto_base_x = anchura / 2;
        double punto_base_y = altura / 2;
        for (double i=0; i<Math.PI; i+=(Math.PI / 12))
            g.drawLine( (int) (punto_base_x - punto_base_x * Math.cos(i)),
                        (int) (punto_base_y - punto_base_y * Math.sin(i)),
                        (int) (punto_base_x + punto_base_x * Math.cos(i)),
                        (int) (punto_base_y + punto_base_y * Math.sin(i)));
    }
}

Vista previa de la creación:

Applets

Después de esas aplicaciones básicas para familiarizarme con el lenguaje, llegó la hora de probar a hacer applets. Buscando por Google, he llegado a un blog que leía hace tiempo, y que ya ni me acordaba que era una mina de códigos de aplicaciones Java. El blog en cuestión es Casidiablo, el cual me parece que lo conocí en la época en la que foreaba por ElHacker.net.
A lo que iba. Que en el blog de Casidiablo he estado mirando códigos de Applets. Para saber si iba a tener problemas con la compilación, construcción o ejecución de los applets. Para ello, he cogido directamente el código de un applet ( de los tantos que tiene aquí ) y lo he pegado en NetBeans:

// Nuestro primer subprograma en Java.
// Paquetes de Java
import java.awt.Graphics; // importar la clase Graphics
import javax.swing.JApplet; // importar la clase JApplet
public class SubprogramaBienvenido extends JApplet
{
    // dibujar texto en el fondo del subprograma
    public void paint( Graphics g )
    {
        // llamar a la versión del método paint de la superclase
        super.paint( g );
        // dibujar un String en la coordenada x 25 y la coordenada y 25
        g.drawString( "¡Bienvenido a la programación en Java!", 25, 25 );
    }// fin del método paint
}
// fin de la clase SubprogramaBienvenido

Este applet, en teoría, debería mostrar el mensaje "¡Bienvenido a la programación en Java!". Le doy para compilar, construir, y me dice que no hay errores BUILD SUCCESSFUL. Medio camino hecho. Ahora, creo un archivo HTML en el mismo directorio que el archivo  .class con el siguiente codigo:

<html>
<head>
<title>Java Applet</title>
</head>

<body>
<applet code="SubprogramaBienvenido.class" height="200" width="200">
</applet>
</body>
</html>

El resultado al abrir el HTML en el navegador es el siguiente:


Para la siguiente, intentaré hacer alguna aplicación básica en forma de applet

Números primos de 2 a 1000

Una simple aplicación que imprime en pantalla números primos entre 2 y 1000.

Creo un ArrayList donde almaceno el número 2. Despues, creo un bucle de 3 a 1000 de dos en dos (por que no merece la pena mirar si un número par es primo, porque todos son divisibles por 2). Cada número es pasado como argumento a una función que evalua si un número es o no primo, si lo es, lo añade al ArrayList primos, si no lo es, simplemente no hace nada. Para terminar, imprime en pantalla cada uno de los elementos del ArrayList primos, y para terminar, cuantos hay.

En la función isPrimo, se coge como parámetro un número entero. Crea un bucle que va desde el primer elemento hasta la raíz cuadrada del número pasado como parámetro. Sé que el código está hecho de tal forma que siempre evaluará un número más de lo que debería (para 3, evaluaría el 2, que es mayor a sqrt(3). Para 5, evaluaría el 3 que es mayor a sqrt(5). Para 7, evaluaría el 3 también, ...). Si en algún momento, el resto de la división entre el número y alguno de los números primos es 0 (que el número primo es uno de las factores del número a analizar), devuelve false. Si después de hacer todas las comprobaciones, ninguno ha sido factor, señal de que el número a analizar era primo, por lo que devuelve true.


import java.util.ArrayList;
import java.util.Iterator; 

public class Main {
    static ArrayList primos;
    public static void main(String[] args) {
        int i;
        primos = new ArrayList();
        primos.add(2);
        for (i=3;i<1000;i+=2)
        {
            if (isPrimo(i))
                primos.add(i);
        }
        Iterator iter = primos.iterator();
        while (iter.hasNext())
            System.out.println(iter.next());
        System.out.println(primos.size());
    }
    static boolean isPrimo(int num)
    {
        Iterator<integer> iter=primos.iterator();
        boolean fin = false;
        int valor;
        while (iter.hasNext() && !fin)
        {
            valor = iter.next();
            fin = valor >= Math.sqrt(num);
            if ((num % valor) == 0)
                return false;
        }
        return true;
    }
}

De momento, esto no tiene más misterios. La cosa va bien, no me quejo. Todavía no entiendo porque primos e isPrimo tienen que ser abstract, ni qué hace que lo sean. Pero ya lo descubriré.

Palíndromos

Aplicación que comprueba si una palabra o frase se lee igual de derecha a izquierda y viceversa:

public class Palindromo {
    public static void main(String[] args) {
        String[] palabras = {"Palindromos","asdfdsa","AsDdSa","Sale El As","No palindromos","Cualquier frase","O palabra","Que no sea palindromo"};
        int indice = (int)(Math.random() * palabras.length);
        System.out.println("Palabra utilizada: "+ palabras[indice]);
        //Quitar espacios y convertirlo a minusculas para hacer las comparaciones
        String modificado = palabras[indice].replaceAll(" ","").toLowerCase();
        System.out.println("Palabra modificada: "+ modificado);
        int i=0;
        boolean palin = true;
        while (palin && i < modificado.length() / 2)
        {
            if (modificado.charAt(i) != modificado.charAt(modificado.length() -1 -i))
                palin = false;
            i++;
        }
        if (palin)
            System.out.println("Palindromo");
        else
            System.out.println("NO Palindromo");
    }
}

Implementación del mismo como función:

public class Palindromo {
    public static void main(String[] args) {
        String[] palabras = {"Palindromos","asdfdsa","AsDdSa","Sale El As","No palindromos","Cualquier frase","O palabra","Que no sea palindromo"};
        int indice = (int)(Math.random() * palabras.length);
        System.out.println("Palabra utilizada: "+ palabras[indice]);
        if (palindromo(palabras[indice]))
            System.out.println("Palindromo");
        else
            System.out.println("NO Palindromo");
    }
    static boolean palindromo(String palabra)
    {
        //Quitar espacios y convertirlo a minusculas para hacer las comparaciones
        String modificado = palabra.replaceAll(" ","").toLowerCase();
        int i=0;
        while (i < modificado.length() / 2)
        {
            if (modificado.charAt(i) != modificado.charAt(modificado.length() -1 -i))
                return false;
            i++;
        }
        return true;
    }
}

Primeros ejercicios en Java

Todavía puede que sea temprano para echar fuegos artificiales, pero en una semanita he conseguido más de lo que consegui en mis anteriores intentos. Como todavía sigo con la espinilla del scanf de C, por lo que los "lee un número del teclado" lo interpretaré como "número aleatorio":

public class Main {
    public static void main(String[] args) {
        int num1, num2;
        num1 = (int)(Math.random() * 100) + 1;
        num2 = (int)(Math.random() * 100) + 1;
        System.out.println("Num1: "+ num1 +"\tNum2: "+ num2);
    }
} 
Para las cadenas de caracteres, me basaré en la misma idea. Añadir unas palabras a un array de Strings, y acceder a ellos mediante un numero aleatorio:


public class Main {
    public static void main(String[] args) {
        String[] palabras = {"Intentando","aprender","JAVA","de","momento","la cosa","pinta","bastante","bien","la verdad","SaLuDoS"};
        int indice = (int)(Math.random() * 10);
        System.out.println("Palabra utilizada: "+ palabras[indice]);
    }
}

Y weno, el primer ejercicio que he realizado a partir de aquí, ha sido el de escribir una palabra formando un cuadro, lo que sería lo siguiente:

public class CuadroPalabra {
    public static void main(String[] args) {
        String[] palabras = {"Intentando","aprender","JAVA","de","momento","la cosa","pinta","bastante","bien","la verdad","SaLuDoS"};
        int indice = (int)(Math.random() * 10);
        System.out.println("Palabra utilizada: "+ palabras[indice]);
        
        int i,j;
        System.out.println(palabras[indice]);
        for (i=1;i<palabras[indice].length()-1;i++)
        {
            System.out.print(palabras[indice].charAt(i));
            for (j=1;j<palabras[indice].length()-1;j++)
                System.out.print(" ");
            System.out.print(palabras[indice].charAt(palabras[indice].length()-i-1));
            System.out.print("\r\n");
        }
        for (i=palabras[indice].length()-1;i>=0;i--)
        {
            System.out.print(palabras[indice].charAt(i));
        }
        System.out.println("");
    }
}

Primeros pasos con el Netbeans

Mas bien, diría que gateando. Despues de ponerme a leer unos cuantos tutoriales y cursos de Java desde cero, esta vez creo que la cosa pinta mejor que en mis anteriores fracasos. Seguramente se deba a que esta vez lo estoy tomando con mas calma, sensatez y paciencia. Por mucho que lo intente, no consigo familiarizarme con tanto static, abstract, interface, ... en C todo parecía taaaan bonito... Pero supongo que este tema lo solucionará el tiempo y la experiencia.

Bueno, lo dicho, el HelloWorld y las pruebas con las instrucciones básicas de control de flujo no me han dado ningún problema. Sólo me faltaría que no consiguiera compilar un while. Ahora toca buscar enunciados del estilo de los ejercicios que nos mandaban hacer en las clases de programación. Mirando por Google, he dado con un par de páginas donde aparecen unos ejercicios que parecen ser adecuados (algunos incluso absurdamente fáciles, pero prefiero hacerlos e ir acomodandome en el lenguaje, a fracasar estrepitosamente de nuevo).

Próximamente, más y esperemos que mejor

Presentación y declaración de intenciones

Como todo nuevo blog, este debería comenzar por una presentación. Soy un jovenzuelo que lleva unos cuantos años (más de los que quisiera) dedicándose al mundo de la infórmatica.
Mi historia con Java comenzó hace ya un par de años, y fue un auténtico fracaso, era joven e insensato. En aquel entonces, tenía conocimientos en C/C++, VB, PHP y algunos lenguajes poco usados. A medida que empecé a realizar programas básicos, llegó el momento en el que necesitaba meter los datos por teclado, y la impotencia que sentí al no conseguir hacer un "scanf" en Java, me llevo a aparcarlo temporalmente. Ahora, me ha entrado de nuevo el gusanillo de aprender Java, más que nada para realizar programillas para Android y algún que otro applet para las páginas que vaya haciendo.
En este blog, comenzaré desde lo más básico, redactando mis andaduras a medida que vaya aprendiendo. Agradecería que si algún gurú de Java pasa por aquí, me de algúnos consejos siempre que no le suponga un tremendo esfuerzo.
En resumen, en este blog voy a despotricar sobre Java debido a mi ignoracia. Saludos