viernes, 30 de enero de 2015

Clases Genéricas en Java

En la entrada anterior usamos la notación: ArrayList<String>, cómo podemos ver, esta notación utiliza los símbolos de < y > para indicar el tipo de los objetos que tendrá el ArrayList, pues bien, en esta entrada vamos a explicar el por qué de esa notación.

Cómo vimos en la anterior entrada dedicada a usar la clase ArrayList vimos que para utilizarla usábamos la notación ArrayList<String> utilizando los símbolos < y >, pues bien, las clases que requieren este tipo de parámetros entre estos símbolos se denominan clases genéricas.

Estas clases genéricas, al contrario que otras clases en Java que sus objetos son de un tipo único, no definen un tipo único sino que pueden definir muchos tipos, ya que el tipo que definirán será el que se incluya entre los símbolos < >. 

Por ejemplo podemos crear un ArrayList de String llamado nombres:

private ArrayList<String> nombres;

Podemos crear un ArrayList de Vehiculos llamado coches si tenemos la clase Vehiculos en nuestro proyecto:

private ArrayList<Vehiculos> coches;

De esta forma podemos añadir objetos de la clase Vehiculos al ArrayList coches y tener así una colección de objetos de la clase Vehiculos.

Cómo vemos con las clases genéricas además de crear colecciones de objetos de los tipos predefinidos en Java podemos crear colecciones de objetos de las clases que tenemos en nuestro proyecto abriéndonos así un gran abanico de posibilidades en nuestros proyectos.

Pudiera ser que en ocasiones definiéramos varios campos con la misma clase cómo por ejemplo:
private ArrayList<Vehiculos> coches;
private ArrayList<Vehiculos> motos;

En estos casos debemos tener cuidado pues estos campos no pueden ser asignados uno a otro aún cuando sus tipos derivan de la misma clase, pues son tipos diferentes.

jueves, 29 de enero de 2015

Clase ArrayList en Java

Vamos a ver cómo podemos usar una clase de biblioteca en Java, en concreto vamos a usar la clase ArrayList y vamos a ver cómo crear un pequeño programa para guardar números de teléfono.

Para poder usar la clase ArrayList en nuestra aplicación lo primero que tenemos que hacer es importarla a la clase donde la vayamos a utilizar de la forma en que dijimos en la entrada anterior y que sería así: import java.util.ArrayList;

En nuestro pequeño programa vamos a crear una agenda de teléfonos, sólo vamos a almacenar el número de teléfono sin nombre ni nada para hacerlo más sencillo y se pueda entender mejor. Una vez se entienda es bastante sencillo ir añadiendo campos y todo lo que queramos.

Nuestra clase se va a llamar AgendaTelefonos y va a tener un único campo que será donde se almacenen los teléfonos, en concreto será este: private ArrayList<String> telefonos; con esta línea de código estamos creado un ArrayList de tipo String llamado telefonos, es decir una colección de String que se llama telefonos, la palabra private es un modificador de acceso que en este caso hace que ese campo solo se pueda usar en esta clase, si fuera public podría ser usado por otras clases, en entradas posteriores iremos hablando más de los modificadores. Cómo estamos usando de tipo String podremos almacenar caracteres ya sean letras o números.

Una vez definido ese campo lo inicializaremos en el constructor de la siguiente manera: telefonos = new ArrayList<String>();

Seguidamente tendremos los métodos que en este pequeño programa serán de modificación y de acceso. En concreto tendremos un método para almacenar un teléfono que usará el metodo add de ArrayList, también tendremos otro que nos diga cuantos teléfonos tenemos almacenados y otro método que nos los imprimirá en pantalla.

Os dejo el código de la clase completa debidamente comentado para que podáis entenderlo mejor:


//importamos la clase ArrayList para poder usarla
import java.util.ArrayList;

public class AgendaTelefonos
{
   
    //ArrayList de nombre telefonos donde los almacenaremos
    private ArrayList<String> telefonos;

    //constructor que inicializa el campo telefonos
    public AgendaTelefonos()
    {
        telefonos = new ArrayList<String>();
    }

    //método que añade un telefono a telefonos
    public void almacenarTelefono(String telefono)
    {
        telefonos.add(telefono);
    }

    //método que devuelve la cantidad de telefonos que tenemos almacenados
    public int cantidadTelefonos()
    {
        return telefonos.size();
    }

    
    //método que imprime los telefonos que tenemos almacenados
    public void imprimirTelefonos()
    {
        for(int i=0; i<cantidadTelefonos(); i++)
        {
            System.out.println(telefonos.get(i));
        }
    }

}


El código conforme está lo copiáis y pegáis en Bluej y funciona perfectamente para que podáis hacer vuestras pruebas y modificaciones.

Si tenéis alguna duda no dudéis en ponerlo en los comentarios.

Saludos a tod@s!!

;)

miércoles, 28 de enero de 2015

Biblioteca de Clases en Java

La biblioteca de clases de Java es una colección de muchísimas clases ya creadas que podemos usar en nuestras aplicaciones.

Java llama a estas bibliotecas paquetes (packages) y podemos usarlos en nuestras clases cómo si fueran clases creadas por nosotros mismos pudiendo usar sus métodos y funciones con total libertad.

Dentro de estos paquetes podemos encontrar clases que nos ayudan en la parte gráfica de nuestros programas como Swing y AWT que nos aportan infinidad de métodos para ayudarnos en la parte gráfica de nuestros programas, también podemos encontrar el paquete util que nos aporta innumerables posibilidades y utilidades para nuestras aplicaciones, etc.

Para usar estos paquetes en nuestro programas lo que tenemos que hacer es importarlos con la sentencia import que se coloca al principio de la clase justo encima del nombre de la clase, una vez la importemos podemos usar sus métodos y funciones cómo si fuera una clase creada por nosotros.

Por ejemplo si queremos usar la clase ArrayList debemos saber que esta se encuentra dentro del paquete util por lo que para usarla en una clase que se llame por ejemplo Running tendriamos que importarla así:

import java.util.ArrayList;

public class Running
{

       //aquí va el código de la clase donde ya podemos usar la clase ArrayList

}

Así de fácil es usar la biblioteca de clases en Java. Otra forma de importar clases o paquetes enteros es usando .*, si queremos usar dentro de la misma clase varias clases del paquete util en vez de importarlas una por una, podemos importarlas de la siguiente manera:

import java.util.*;

De esta forma importamos el paquete util entero con todas sus clases, pudiendo hacer uso de todas sin necesidad de tener que importarlas una por una.

Si queremos conocer de cuantas clases disponemos y que hace cada clase, así cómo sus parámetros, métodos etc lo podemos ver en bluej entrando en Ayuda y ahí en Librerías de Clases Java, una vez le demos se nos abrirá la siguiente ventana y ahí podemos ver todas las clases de las que disponemos y lo que podemos hacer con cada una de ellas:

paquetes de clases en Java
Biblioteca de Clases en Java

En la próxima entrada veremos cómo hacer una clase completa en la que usar la clase ArrayList del paquete util y ver cómo podemos hacer colecciones con ella.

Cualquier cosa no dudéis en ponerla en los comentarios.

;)

martes, 27 de enero de 2015

Colecciones de objetos en Java

Los objetos en Java pueden agruparse para formar colecciones, por tanto podemos definir colección de objetos en Java cómo un grupo de objetos.

Cuando hacemos programas o aplicaciones es común agrupar algunos objetos para poder usarlos mejor. Ejemplos de programas que usan colecciones pueden ser las agendas, aplicaciones de control de bibliotecas, parkings, etc.

Java nos permite que esas colecciones de objetos sea de tamaño fijo, que no se pueda cambiar su número una vez creada, o de tamaño flexible, que se pueda cambiar según se vaya necesitando, cómo por ejemplo una agenda de teléfonos en la que a la hora de crearla no sabemos cuantos números podremos tener en el futuro y es necesario que pueda ir aumentando su tamaño a la hora de ir incrementando los números que le vayamos poniendo.

En Java tenemos muchas formas de hacer colecciones de objetos, lo mas sencillo es usar la clase ArrayList de la que hablaremos más adelante y que cómo veremos nos permitirá trabajar con colecciones de una manera muy fácil y sencilla. Otras formas de agrupar objetos en Java puede ser el uso de estructuras de datos más avanzadas cómo los TADs (Tipos abstractos de datos) cómo colas, listas, árboles, etc. que también veremos más adelante.

En la próxima entrada veremos cómo podemos usar en Java la biblioteca de clases para que podamos usar en nuestras aplicaciones la clase ArrayList y poder crear así nuestras colecciones de objetos o datos.

Cualquier cosa no dudéis en ponerla en los comentarios.

Saludos a tod@s!!

;)

lunes, 26 de enero de 2015

¿Qué es el Firmware?

En palabras de andar por casa podemos definir firmware cómo el software que controla un hardware.

Actualmente todos los dispositivos que manejamos a diario (móviles, tablets, smartwatch, etc) tiene un software para controlar todas las características que tiene su hardware. Ese software es lo que se entiende por firmware, es cómo si fuera un sistema operativo de ese dispositivo en concreto pero sin serlo, el sistema operativo se encontraría en un nivel superior y sería el que controlaría el firmware.

Antiguamente los dispositivos se hacían con unas características específicas y determinadas y durante su vida no se podían cambiar, es decir el dispositivo desde que lo comprabas hasta que dejabas de usarlo era siempre igual y tenía las mismas funciones, en la actualidad eso no pasa, es común que por ejemplo compremos un teléfono y al poco tiempo veamos que podemos realizar una actualización de firmware, pues bien esa actualización lo que hace es actualizar el software que controla el dispositivo. Esto lo que ocasiona a veces es que muchos productos los lancen al mercado sin haberlos probado lo suficiente y le van añadiendo mejoras a su firmware a medida que van detectando los errores o carencias que tiene. Ejemplos de esto tenemos en los móviles, tablets, relojes de entrenamiento cómo garmin, polar, suunto, etc.

Con estas posiblidades de actualizar el firmware podemos encontrarnos con dispositivos que cuando son lanzados al mercado son un poco ineficientes, tienen errores, etc y a medida que los vamos actualizando van mejorando. 

En otras ocasiones podemos encontrar algunas actualizaciones de firmware que hacen que funcione peor que antes, por eso mi recomendación cuando veáis que tenéis una actualización de firmware disponible es que esperéis unos días a ver los comentarios y opiniones de la gente que ya lo ha instalado y después lanzaros a instalar una vez que tengáis la seguridad de que funciona bien.

En resumen, el firmware es el software encargado de controlar el hardware del dispositivo, por lo que si alguna vez tenéis que actualizarlo en alguno de vuestros dispositivos aseguraos de que esa actualización va a mejorar el que tenéis actualmente porque sino al tener un firmware "malo" que no controla bien el hardware o no lo aprovecha bien, tendréis una mala experiencia de usuario.

Cualquier cosa no dudéis en ponerla en los comentarios.

;)

jueves, 22 de enero de 2015

This en Java

Con la palabra clave this hacemos referencia al objeto actual, lo que nos permite solucionar problemas cuando hay sobrecarga de nombres, es decir cuando un mismo nombre es usado por entidades diferentes.

This se usa a menudo para solucionar los conflictos de nombres, también se podrían solucionar cambiando el nombre de las variables por otros pero a veces tenemos un nombre que define perfectamente a la variable o al método por lo que no queremos cambiarlo, es por esto que se usa la palabra clave this en la asignación y eliminar así los conflictos.

Un ejemplo en el que podemos ver cómo se usa podría ser el siguiente:

Tenemos una clase de nombre Superacion en la que en los campos hemos declarado 3 variables por ejemplo:

int km;
int peso;
int velocidad;

Y en el constructor de la clase tenemos los siguiente parámetros:

public Superacion( int km, int peso, int velocidad)

Al tener los parámetros el mismo nombre que los campos podemos tener problemas a la hora de usar una variable u otra ya que cuando se está ejecutando el constructor tendriamos 6 variables, 3 de los campos y 3 de los parámetros, que es lo que se entiende cómo sobrecarga de nombres.  Esto no es un problema en java, puede haber variables y parámetros con el mismo nombre, pero al usarlas si podríamos tener problemas, Java especifica que siempre se usará la declaración mas cercana encerrada en un bloque. Dado que el parámetro está declarado en el constructor y el campo está declarado en la clase, la variable que se usará será la del parámetro pues su declaración está más cerca de la sentencia que lo usa, por tanto si queremos acceder al campo necesitamos de un mecanismo que nos permita hacerlo, ese mecanismo es la palabra clave this que nos permite hacer referencia al objeto actual y a sus campos.

Por ejemplo si quisieramos asignar el valor de los parámetros a los campos de la clase el constructor quedaría de la siguiente manera:

public Superacion( int km, int peso, int velocidad)
{
       this.km=km;
       this.peso=peso;
       this.velocidad=velocidad;
}

De esta forma estariamos asignandole a los campos los valores de los parámetros.

Muchas veces es mejor cambiar el nombre de los parámetros o los campos y ya está, pero si eso no es posible o preferimos no hacerlo sabemos que con la palabra clave this podemos hacer uso de los campos cómo hemos visto.

Cualquier duda no dudéis en ponerla en los comentarios.

Saludos a tod@s!!

;)

miércoles, 21 de enero de 2015

Llamadas a métodos en java

En java podemos utilizar los métodos de una clase dentro de la misma clase y también podemos usar en una clase métodos que están en otras clases.

Cuando llamamos a un método desde la misma clase en la que está declarado decimos que es una llamada interna. Cuando llamamos a un método de otra clase decimos que es una llamada externa.

Imaginemos que tenemos en una clase el siguiente método declarado:

public void entrenarMucho()
{
       kilometros++;
}

Ahora queremos usar ese método en otro método de la misma clase, lo que tenemos que hacer es lo siguiente:

public void usamosElOtroMetodo()
{
       entrenarMucho();
}

Cómo vemos, para usar un método que está declarado en la misma clase que lo queremos usar solo tenemos que poner su nombre y () si no tiene parámetros o () poniendo dentro de los paréntesis los valores de los parámetros que tuviera dicho método.

Vamos ahora a ver cómo se hace uso de un método que está en otra clase. Imaginemos que tenemos en otra clase el mismo método que arriba entrenarMucho y que la clase se llama Entrenar, para usarlo en otra clase lo que tendríamos que hacer es lo siguiente:

Primeramente tenemos que crear un objeto de la clase Entrenar para poder usar sus métodos y lo haríamos así:

Entrenar objetoDeLaClaseEntrenar=new Entrenar();

Ahí en esa línea hemos creado el objeto objetoDeLaClaseEntrenar a partir de la clase Entrenar y apartir de él ya podemos usar los métodos de esa clase en la clase donde hemos declarado el objeto (usando static podriamos usarlo sin crear el objeto, pero eso ya lo veremos más adelante). Una vez que tenemos el objeto para usar sus métodos se usa la notación de punto y sería así:

objetoDeLaClaseEntrenar.entrenarMucho();

Así estariamos usando el método entrenarMucho de la clase Entrenar. El nombre objetoDeLaClaseEntrenar se puede cambiar y poner lo que queráis, lo he puesto así tan largo para aclarar un poco y que no fuera tanto lío.

El uso de métodos de un método a otro, de una función, entre clases, etc es muy importante y a medida que vayamos creando proyectos mas elaborados y sofisticados nos daremos cuenta de las grandes posibilidades y opciones que nos ofrecen por lo que es muy importante dominarlo y entenderlo correctamente.

martes, 20 de enero de 2015

Ramificación y poda

Este esquema algorítmico se utiliza en problemas en los que buscamos la optimización en la solución que queremos encontrar.

Estos algoritmos de ramificación y poda son menos eficientes que los algoritmos voraces por lo que su aplicación está indicada solamente cuando no se pueda resolver el problema con algoritmos voraces.

Al igual que en los algoritmos de vuelta a atrás se exploran todas las alternativas que permiten llegar a la solución pero ahora en lugar de cortar la exploración de los caminos que no llevan a una solución, se evita la de aquellos que llegan a unas soluciones peores que otras ya que aquí lo que perseguimos es la optimización.

Por regla general la ramificación y poda la podemos encuadrar cómo un esquema para explorar un grafo dirigido implícito. En este caso se busca la solución óptima del problema que tenemos entre manos y vamos explorando los nodos de acuerdo a la función que se quiere optimizar estableciendo así preferencias entre los nodos que nos quedan por visitar. La búsqueda se va dirigiendo por el nodo más prometedor por lo que requiere una cola de prioridad para gestionar los nodos. Una vez que se selecciona un nodo se procede con una fase de ramificación en las que se generan las soluciones parciales a dicho nodo, a continuación se podan (eliminan) las ramas que no pueden llegar a una solución y aquellas que no pueden llegar a una solución mejor. Por ello en cada nodo vamos calculando una cota optimista del posible valor de las soluciones que se pueden construir a partir de él y que nos permitirá ver si se puede encontrar una solución mejor o no por lo que no tendría sentido seguir mirando y se realizaría la poda.

Problemas típicos que se resuelven con este tipo de algoritmos son la asignación de tareas, selección de tareas, distancia de edición, etc.

Si queréis que profundicemos más en este tipo de algoritmos no dudéis en ponerlo en los comentarios.

;)


lunes, 19 de enero de 2015

Algoritmos de Vuelta atrás

Con estos algoritmos vamos a intentar resolver problemas en los que sólo podemos recurrir a realizar una búsqueda exhaustiva recorriendo todas las posibles soluciones hasta encontrar la que buscamos o hasta que la búsqueda finalice.

En muchas ocasiones nos encontramos con problemas en los que no podemos aplicar ningun algoritmo específico para resolverlo, por lo que tenemos que recurrir a realizar una búsqueda exhaustiva de las posibles soluciones.

El esquema de vuelta atrás para resolver un problema realiza un recorrido en profundidad del grafo de un problema, podando aquellas ramas para las que el algoritmo puede comprobar que no hay solución al problema. Las soluciones se van construyendo de forma incremental. En su forma más básica, la vuelta atrás es similar a un recorrido en profundidad dentro de un grafo dirigido. El objetivo de estos algoritmos de vuelta atrás es encontrar una solución o encontrar todas las posibles soluciones al problema dado.

Los pasos que generalmente tiene todo algoritmo de vuelta atrás son: recoger todas las opciones posibles en que se puede extender la solución, comprobar las opciones que quedan por explorar, comprobar que se haya completado la solución al problema y obtener la solución.

Este tipo de esquemas algoritmicos es bueno para realizar problemas de coloreado de grafos, ciclos Hamiltonianos, etc.

Si queréis que profundicemos más en este tipo de algoritmos no dudéis en ponerlo en los comentarios.

Saludos a tod@s!! ;)

viernes, 16 de enero de 2015

La Programación Dinámica

La técnica de la programación dinámica es una técnica que se utiliza en programación y que utiliza resultados parciales que se van produciendo durante la resolución de los problemas para llegar al resultado final.

Esta forma de resolver problemas, cómo ya hemos dicho anteriormente, va resolviendo el problema registrando los resultados parciales que va obteniendo y que posteriormente utiliza para obtener la solución final, lo que le permite reducir el coste computacional mejorando así su eficencia.

Por tanto podemos afirmar que la programación dinámica es una técnica con la que podemos reducir el coste de ejecución de un algoritmo memorizando las soluciones parciales que vamos obteniendo para así llegar a la solución final del problema. Algunos problemas en los que es aplicable esta técnica se pueden resolver con la técnica de divide y vencerás que vimos en una entrada anterior. 

Por regla general los resultados que se van obteniendo al aplicar los algoritmos con esta técnica se van almacenando en una tabla de la que posteriormente se van tomando cuando el algoritmo los vuelve a necesitar. Los primeros datos corresponden a los subproblemas más sencillos y a partir de ellos se van construyendo de forma incremental las soluciones a los subproblemas mayores hasta llegar a la resolución del problema completo.

La reducción del coste computacional de la que hablabamos antes tiene un precio y ese precio es el incremento del coste espacial ya que el almacenamiento de las soluciones parciales que vamos obteniendo requiere incrementar el espacio dedicado a los datos que usará nuestro algoritmo.

La forma en la que se aplica esta técnica es muy dependiente del problema que tratemos y la estructura de datos que se utilice para su resolución pero cómo regla general podemos establecer la siguiente secuencia para resolver un problema utilizando la programación dinámica. Primeramente hay que establecer las ecuaciones que representan el problema que tenemos que resolver, seguidamente tenemos que identificar cuales son los resultados parciales que vamos a ir obteniendo y cómo estos nos van a permitir llegar a la solución final. Tras estos pasos tenemos que construir la tabla de resultados parciales que nos llevará a la solución final. Primeramente la inicializaríamos con los casos base de nuestro problema, después la iríamos llenando de forma que se vayan introduciendo primero los resultados parciales que no requieren pasos anteriores para después llenarla con los resultados que necesitan de esos resultados parciales que ya hemos obtenido en los pasos anteriores para así llegar al resultado final.

Esta forma de programación dinámica se utiliza en muchos problemas cómo por ejemplo en los coeficientes binomiales, problemas de devolución de cambio, la multiplicación asociativa de matrices, la mochila, etc.

La programación dinámica nos abre un mundo lleno de posibilidades a la hora de resolver problemas y de utilizar algoritmos de una forma más eficiente como hemos dicho anteriormente.

Si queréis que profundicemos más sobre esta técnica no dudéis en ponerlo en los comentarios.

;)

jueves, 15 de enero de 2015

Estrategia Divide y Vencerás utilizada en algoritmos

La técnica de divide y vencerás utilizada en algoritmos se basa en la descomposición de un problema en subproblemas del mismo tipo más pequeños, lo que permite disminuir su dificultad y encontrar la solución más fácilmente.

Para emplear este algoritmo lo que tenemos que hacer es descomponer el problema que tengamos entre manos en subproblemas más pequeños, ir haciendo una resolución recursiva de los subproblemas y combinar o utilizar las soluciones de esos subproblemas para encontrar la solución al problema planteado.

Este modo de resolver problemas utiliza el principio de inducción sobre los diversos ejemplares del problema, de esta manera supone solucionados los subproblemas y utiliza las soluciones de los mismos para componer la solución final del problema.

Un ejemplo de esta técnica es el algoritmo de Euclides del año 300 a.C. aprox. que calcula el Máximo Cómun Divisor de dos enteros.

Ejemplos que nos permiten entender mejor cómo funciona esta técnica de solucionar problemas es la ordenacion por fusión o mergesort que es un problema que consiste en que dado un vector de enteros tenemos que ir dividiéndolo y ordenando las mitades por separado, para una vez ordenados fusionarlos y obtener la solución final.

El puzzle tromino, la ordenación rápida o quicksort y el cálculo del mayor elemento de un vector son problemas en los que se puede ver cómo funciona esté esquema algorítmico de divide y vencerás para encontrar la solución.

Si queréis mas información sobre esta estrategia de divide y vencerás y así cómo la solución a los ejemplos citados no dudéis en ponerlo en los comentarios.

algoritmo divide y vencerás
Divide y Vencerás

miércoles, 14 de enero de 2015

Algoritmos voraces

Una algoritmo voraz es un tipo de algoritmo que nos permite resolver un determinado problema de una forma concreta.

Este tipo de algoritmos voraces se aplica a problemas de optimización en los que la solución se puede construir paso a paso sin necesitar ningún dato o decisión anterior. Generalmente estos algoritmos encuentran un conjunto de candidatos que constituyen la solución y que la optimiza. Es usado en problemas de planificación, problemas que se pueden modelar con grafos y en los que se suele realizar una búsqueda, cálculo de recorridos, optimización de pesos, etc.

Por regla general los problemas que se suelen resolver con este tipo de algoritmos constan de unos candidatos y se trata de encontrar una solución basada en obtener un subconjunto de esos candidatos o una secuencia ordenada de los mismos de manera que se optimice una función objetivo (lo que queramos conseguir).

Para aplicar este tipo de algoritmos se suele trabajar por etapas o fases,  tratando un candidato en cada fase. Hay que ir seleccionando en cada etapa al candidato más "bueno" para lo que buscamos de los aún disponibles y decidir si se incluye o no en la solución.

Trabajando así podemos ver que se examina una vez cada candidato y se decide si se selecciona o se rechaza. Luego se intentará seleccionar al mejor de los candidatos restantes hasta encontrar la solución que se busque. Si el algoritmo es correcto, la primera solución encontrada es la solución óptima.

La principal característica que distingue los algoritmos voraces de otros tipos de algoritmos es que nunca se vuelve a atrás y se anula una decisión ya tomada por lo que cuando se incorpora un candidato a la solución, este permanece hasta el final. Del mismo modo cuando se rechaza un candidato no se vuelve a tener en cuenta.

Este tipo de algoritmos voraces pueden parecer sencillos y al no volver a "ver" los candidatos que ya han sido tratados suelen resultar eficientes en la mayoría de los casos.

Dos problemas de grafos muy conocidos que se resuelven con este tipo de algoritmos son hallar un árbol de recubrimiento de distancia o coste mínimo y calcular el camino de coste mínimo entre un nodo y los demás. Algunos algoritmos muy conocidos para resolverlos son los algoritmos de Prim, algoritmo de Kruskal, algoritmo de Dijkstra.

Otro problemas conocidos que se pueden resolver con algoritmos voraces son el problema de la mochila con objetos fraccionables, problemas de mantenimiento de la conectividad, problemas de mensajería urgente, etc.

Si queréis que profundicemos más sobre este tipo de algoritmos o que resolvamos algún problema con ellos no dudéis en ponerlo en los comentarios ;)


martes, 13 de enero de 2015

¿Qué es un grafo y cómo se puede representar?

Un grafo es una estructura de datos avanzada, que se usa muy frecuentemente en algunos esquemas algorítmicos.

Podemos definir grafo como una colección de nodos o vértices unidos por líneas o aristas. Los nodos o vértices representarían los objetos y las aristas las relaciones entre ellos.

Los grafos pueden ser dirigidos o no, son dirigidos cuando las líneas o arístas están orientadas en alguna dirección, sino estamos ante un grafo no dirigido.

El grado de un vértice en un grafo no dirigido es el número de aristas que salen o entran de él. En cambio si el grafo es dirigido se puede hablar de grado de entrada de un vértice (las líneas que entran a él) o grado de salida (las líneas que salen de él).

Un camino en un grafo dirigido es una secuencia finita de arcos entre dos vértices. Un ciclo o circuito es un camino que empieza y termina en el mismo vértice.

Existen varios tipos de grafos entre los que destacan el grafo nulo que es un grafo sin vértices, grafos acíclicos que son los que no contienen ciclos, grafos simples si entre cada par de vértices existe a lo sumo una arista que los una, grafo conexo si para cualquier par de vértices distintos existe un camino que los contiene, etc.

A la hora de representar los grafos tenemos muchas posibilidades entre las que destacan dibujarlo directamente con sus nodos y aristas, las matrices de adyacencia que son matrices cuadradas que solo pueden contener valores 1 o 0 (true o false) en las que el número 1 indica que hay arista entre los dos nodos de esa casilla de la matriz y si hay un 0 indica que no hay arista entre los dos nodos de esa casilla. Las listas de adyacencia también son otro método que se usa bastante para representar nodos, en realidad estás listas son un array de listas, siendo la cantidad de listas igual a la cantidad de nodos del grafo.

Ponemos un ejemplo gráfico de un grafo no dirigido y su correspondiente matriz de adyacencia que cómo vemos, al no estar dirigido nos sale una matriz simétrica:

Grafo no dirigido:
grafo no dirigido
Grafo

Matriz de adyacencia:
matriz de adyacencia grafo 4 nodos
Matriz de adyacencia

lunes, 12 de enero de 2015

Sistema GPS

Tod@s sabemos que es un gps y en alguna ocasión hemos utilizado alguno, pero ¿sabemos realmente cómo es ese sistema y cómo funciona?

GPS es un sistema de posicionamiento que nos permite saber donde nos encontramos.

El funcionamiento de este sistema es muy básico. Se trata de una red de 24 satélites que orbitan alrededor de la tierra a gran altura, cada uno de esos satélites transmite una señal hacia la tierra y nuestros dispositivos gps calculan a partir de esas señales nuestra posición exacta. Por eso cuantos mas satélites tenga sincronizado nuestro dispositivo más precisa será nuestra posición, se necesita un mínimo de 3 satélites para tener una posición un poco fiable, calculando las distancia a la que nos encontramos de cada uno de esos satélites podemos encontrar cual es nuestra posición, por eso si tenemos sincronizados más satélites mas fiable será nuestra posición.

El sistema gps debido a las frecuencias a las que emite su señal no funciona debajo del agua (a profundidad, las señales no atraviesan el agua) a lo mejor en superficie si podemos coger algo de señal dependiendo de la calidad de nuestro dispositivo y tampoco lo hace bajo tierra o con algunos obstáculos que impiden que lleguen las señales a nuestro dispositivo. También si nos encontramos debajo de líneas de alta tensión podremos obtener errores de posicionamiento debido a las interferencias de las ondas eléctricas por lo que debemos tener cuidado.

Nuestros dispositivos para poder entender y utilizar las señales que envían estos satélites utilizan un chip, el mas moderno a fecha de publicación de la entrada es el chip SirfStar V, es el más rápido en localizar las señales y además es compatible con GPS y Glonass lo que lo hace más preciso.

GPS es un sistema de EEUU, existen otros como Glonass que es de Rusia, también se esta creando Galileo por Europa y China también está implementando su propio sistema de posicionamiento global. Todos estos sistemas los puede utilizar libremente cualquier persona del mundo pero cualquiera de los países citados tiene el control total de su sistema pudiendo introducir margenes de error, codificarlo e incluso apagarlo según las circunstancias (en caso de una guerra por ejemplo)

Cómo hemos dicho algunos dispositivos gps actuales montan el chip SirfStar V que es el más moderno a día de hoy y por ello son capaces de leer señales de gps y de glonass lo que les da mayor precisión al comparar más señales y tener más satélites disponibles para coger la señal y calcular nuestra posición.

jueves, 8 de enero de 2015

Qué es Garmin Connect IQ

Garmin Connect IQ es una plataforma creada por Garmin que permitirá a desarrolladores crear aplicaciones para sus dispositivos.

Con Connect IQ, Garmin da la opción a usuarios (que sepan programar) y desarrolladores a crear sus propias apps para sus dispositivos. Teniendo en cuenta los sensores de los que disponga nuestro dispositivo o el dispositivo para el cual estemos desarrollando la aplicación tendremos mas o menos posibilidades. También nos permitirá desarrollar y crear nuestros sensores o gadgets compatibles con nuestro dispositivo y/o con nuestras aplicaciones, por lo que las posibilidades se multiplican.

De momento (a fecha de publicación de la entrada)  los dispositivos para los que se puede empezar a desarrollar son: el Forerunner 920XT, el Vívoactive, el fénix 3 y el epix. Para cada uno podremos crear vistas de reloj, aplicaciones, widgets, campos de datos, etc.

Si queremos empezar a usar Connect IQ es tan fácil cómo entrar en su web http://developer.garmin.com/connect-iq, bajarnos el SDK, instalarlo, unirnos a la comunidad y empezar a crear. 

Para las aplicaciones el lenguaje de programación que se usa es Monkey C que es un lenguaje orientado a objetos similar a lo que podría ser Java, PHP, o Python, por lo que si sabes programar en cualquiera de esos lenguajes no tendrás muchos problemas en iniciarte en Monkey C.

Según mi opinión este movimiento de Garmin de "abrirse" a la entrada de aplicaciones creadas por otras personas es un gran acierto porque, al igual que ocurre con android o apple que tienen millones y millones de apliaciones para instalar en sus dispositivos, le dará un gran catálogo de aplicaciones que permitirá al usuario final unas mejores opciones de personalización de acuerdo a sus gustos, intereses, etc y no tendrá que ceñirse a los clásicos sistemas que no se pueden modificar. Creo también que todas las marcas deportivas, cómo Polar por ejemplo, no tardarán en hacer algo similar para sus dispositivos (Suunto ya lo hace). Así que en no mucho tiempo estaremos viendo relojes deportivos convertidos en SmartWatchs o compitiendo muy de cerca con ellos.

martes, 6 de enero de 2015

Sobrecarga en Java

Entendemos por sobrecarga de una clase cuando esta tiene mas de un constructor o más de un método con el mismo nombre, siempre y cuando se diferencien en los parámetros.

Una clase en java puede tener varios constructores y también varios métodos con el mismo nombre siempre y cuando se diferencien en los parámetros que tengan, es decir, podemos encontrarnos varios constructores en una clase siempre y cuando sus parámetros (número o tipo) sean diferentes.

Todo esto nos proporciona varias maneras de llevar a cabo una tarea mediante diferentes conjuntos de parámetros. Esto es lo que se conoce cómo sobrecarga. Sobrecarga de un constructor en el caso de los constructores y sobrecarga de método en el caso de los métodos.

Aquí os pongo un ejemplo de una clase con sobrecarga tanto en el constructor cómo en los métodos:


public class Robot
{
    private int x, y;

    public Robot()
    {
        x = 0;
        y = 0;
    }

    public Robot(int a, int e)
    {
        x=a;
        y=e;
    }

    public void cambiarPosicion(int h)
    {
        x=h;

    }

    public void cambiarPosicion(int h, int v)
    {
        x=h;
        y=v;
    }

    public int obtenerPosicionX()
    {
        return x;
    }

    public int obtenerPosicionY()
    {
        return y;
    }

}


Cómo vemos tenemos 2 constructores, uno que nos crea el objeto, en este caso Robot en la posición 0,0 y otro que tiene 2 parámetros que nos lo crea en la posición que le demos en los parámetros. Dependiendo de si usamos uno u otro tendremos las posibilidades de asignarle la posición inicial o que nos lo cree por defecto en las coordenadas que tiene en la clase.

También tenemos dos métodos con el mismo nombre que es cambiarPosición, cómo vemos uno solo tiene un parámetro que solo nos cambia la posición x y el otro tiene dos parámetros que nos permite cambiar la posición x y la y. Cómo vemos dependiendo de si usamos uno u otro tendremos dos posibilidades, o cambiar sólo la x o cambiar la x y la y.

Salvo rara ocasión yo no suelo usar la sobrecarga, alguna vez en los constructores si la he usado, pero en los métodos y funciones no la suelo usar, lo que hago es cambiar el nombre por completo del método y así me lío menos al tener los dos métodos más diferenciados.

Cualquier cosa no dudéis en ponerla en los comentarios ;)




lunes, 5 de enero de 2015

Diagrama de Clases en Java

El diagrama de clases muestra las clases de una aplicación y las relaciones entre ellas informándonos sobre el código. Por así decirlo, representa una vista estática de un programa.

Hay que diferenciar diagrama de clases de diagrama de objetos, pues un diagrama de objetos muestra los objetos y sus relaciones en un momento dado de la ejecución de nuestro programa dándonos información en tiempo de ejecución sobre los objetos que tenemos. Por así decirlo, representa la vista dinámica de un programa.

Estos diagramas son de gran utilidad ya que nos ayudan a entender el funcionamiento de nuestro programa/juego/aplicación/etc con un simple vistazo. Bluej nos muestra de forma muy clara los diagramas de clases y las relaciones entre ellas. Usando cuadros para las clases, flechas discontinuas para indicar el uso que hacen unas clases de otras y flechas continuas para indicar el uso de la herencia.

Os pongo varios ejemplos de diagramas de clases en bluej, uno es un diagrama de clases de un Tetris en el que vemos las clases que hay y cómo unas clases hacen uso de otras y el otro diagrama es de un Space Invaders en el que podemos ver cómo unas clases usan a otras y además algunas heredan de otras, también en ese diagrama podemos ver que hay una clase (MusicaJuego) que no recibe y no sale ninguna flecha de ella, lo que nos indica que no está siendo usada por la aplicación.

Diagrama de Clases del juego Tetris:

juego tetris java bluej
Diagrama de Clases del Juego Tetris


Diagrama de Clases del juego Space Invaders:

space invaders bluej java
Diagrama de Clases del Juego Space Invaders


viernes, 2 de enero de 2015

Parámetros en java

Los métodos pueden tener parámetros para proporcionar información. Por lo tanto podemos definirlos cómo un mecanismo que nos ofrece la posibilidad de dar algún tipo de dato a un método.

Los parámetros tienen tipos de dato, es decir, son de un tipo. El tipo define la clase de valores que ese parámetro puede tomar. Por ejemplo un parámetro de tipo int sólo podrá tomar valores enteros.

El encabezado de un método se denomina su signatura y proporciona la información necesaria para poder invocarlo correctamente.



Ejemplo de método sin parámetros:


public void comerChocolate()
{
            //aquí iría el código del método
}


Cómo podemos ver, este método no tiene nada entre los () por lo que no tiene parámetros y al invocarlo lo tendríamos que llamar así: comerChocolate(); sin poner nada entre paréntesis ya que el código de dentro del método no lo necesita.




Ejemplo de método con parámetros:


public void aumentarPeso(int x)
{
            //aquí iría el código del método que en este caso si haría uso o no de la variable x pasada por parámetro
}


Esté método si tiene un parámetro que en este caso es de tipo int (valores enteros), para llamarlo habría que poner: aumentarPeso(20); entre paréntesis tendríamos que poner un entero (también se podría poner una variable de tipo entero, una función que devuelva un entero, etc). Un ejemplo de código que use ese parámetro podría ser:

public void aumentarPeso(int x)
{
peso=peso+x; //incrementaríamos el valor de la variable peso de acuerdo al valor que le pongamos al parámetro cuando ejecutemos el método
}


Los métodos pueden tener muchos parámetros o ninguno y estos pueden ser de varios tipos (int, float, double, String, también pueden ser objetos, vectores, etc). Por lo que podemos encontrarnos métodos que tengan 4 parámetros, uno de ellos int, otro float, otro String y otro double por ejemplo. Otros que tengan 6 parámetros que sean todos int, etc. Las posibilidades son infinitas a la hora de usar los parámetros para pasar información a los métodos.

El uso de parámetros es fundamental para el paso de información de unos métodos a otros y nos ofrece unas posibilidades muy grandes a la hora de añadir funcionalidades a nuestras aplicaciones por lo que es muy importante entender bien su funcionamiento y cómo se usan para poder mejorar nuestros proyectos.