JAVA. Sobre el cast.

El cast es para realizar conversiones de tipo. Mas que ver su utilidad con los tipos básicos (primitivos) o las referencias, dedico esta entrada a ver cuando compila y cuando no compila. El cast compila siempre que nos movamos hacia abajo por la jerarquia de herencia. Debemos recordar que existe una clase de la que heredan todas (TODAS), excepto los tipos básicos (primitivos) ya que no son objetos, la clase Object.

		Object a;
		int [] v;
		int [][] v2;
		
		a = new int [3];
		v = (int []) a; // compila y correcta.
		a = new int [3];
		v2 = (int [][]) a; // compila y no correcta
		v = (int []) v2; // no compila

Además debemos recordar, que todos los vectores (sea cual sea su dimensión) en JAVA, son objetos que herendan de Object.
La penultima conversión compila, porque nos movemos hacia abajo en la jerarquia, sin embargo, no ejecutará de forma correcta, provocando un error de ejecución.
La última conversión no compila, porque no es correcta y no nos movemos hacia abajo en la jerarquia. int [] no hereda de int [][].

Esquema recursivo con almacen.

Preparando la docencia de DAA me encontre un esquema de programación muy interesante e intuitivo, el esquema recursivo con almacen. Cuando ejecutamos una función recursiva, en ocasiones, dicha función vuelve a resolver problemas para los cuales ya ha calculado la solución. Por ejemplo, en el caso de la serie de Fibonacci:

La funcion recursiva que resuelve esta formula es la siguiente (en C/C++)

int fiboR(int n)
{
   int resultado;

   if(n == 0 || n == 1)
      resultado = 1;
   else
      resultado = f(n-1) + f(n-2);
   
   return resultado;
}

Si realizamos el árbol de llamadas recursivas para f(6) podemos observar que existen subproblemas (llamadas) que se vuelven a resolver (desarrollar).


La idea es crear un vector donde guardamos las soluciones de las llamadas ya realizadas y antes de volver a realizarlas comprobar si dicha llamada ya está resuelta. Si ya está resuelta cogeremos la solución del vector y si no la realizaremos. Obviamente cuando resolvemos una llamada la almacenaremos en el vector de soluciones.

Los pasos a seguir serían:
1. Crear un almacen (vector) con las posibles valores para los cuales resuelvo, n en el caso anterior.
2. Incializarlo a -1.
3. Modificar la función recursiva para que:
3.1 Almacene la solución de la llamada resuelta en el almacén.
3.2 Compruebe antes de realizar una llamada si dicha llamada ya está resuelta en el almacen.

Ahí queda eso… en los próximos dias pondre la solución definitiva. 🙂

JAVA. Vectores y polimorfismo.

Este es un problemilla que me surgió el otro dia al intentar «castear» el Object [] que devuelve una colección.
Observemos el código:

public class TestVectores{
          public static void main(String []args){
        // JAVA permite que el vobj apunte a un vector que contenga
        // elementos de su tipo, o derivados. String deriva de 
        // Object.
        Object [] vobj = new String [] {"uno", "dos", "tres"};
        // Conversion valida, vobj esta apuntando a un vector de 
        // String.
        String [] vcads = (String []) vobj;

        ArrayList  vlists = new ArrayList();
        vlists.add("uno");
        vlists.add("dos");
        vlists.add("tres");

        // La conversión de abajo no funciona.
        Object [] vList = vlists.toArray();
        String [] vcads2 = (String []) vList;
        /* vlist.toArray() devuelve un Object [],
         * pero este no está apuntando a un String [], sino a un
         * Object [] en el que cada posición tiene un String.
         */
        // Algo asi internamente..
        Object [] miArrayList = new Object [3];
        miArrayList[0] = new String("uno");
        miArrayList[1] = new String("dos");
        miArrayList[2] = new String("tres");
        // Por esto la conversión no se puede hacer así
        String [] vcads3 = (String []) miArrayList;
        // hay que hacerla elemento a elemento
         }
}

Serie de Fibonacci.

Fibonacci

Fibonacci es una manera única de ver los números y los patrones que están dentro de ellos. Esto a veces puede parecer confuso, pero te sorprendería la cantidad de situaciones y de datos que contienen la secuencia de Fibonacci. Entonces, ¿cómo podríamos aplicar esto a los seres vivos? Muy fácil, si eres capaz de elaborar las fórmulas detrás de él.

Ideas básicas.

–          Cada pareja de conejos tendrá una nueva pareja.

–          En el mes siguiente la nueva pareja es fértil.

–          La función devuelve el número de parejas transcurridos n meses desde un instante inicial mes 1.

–          Las compramos no fértiles.

tablaconejil

Entonces, en el mes n, tengo todas las parejas que tenía en el mes anterior y las que tenía hace dos meses todas tienen una nueva pareja.

F(n) = F(n-1) + F(n-2), sumamos las parejas que tenía antes y una pareja nueva por cada pareja que tenía hace dos meses.

F(0) = F(1) =  1

Scale, Rotate and Translate (Move) in RhinoScript vbScript

Un ejemplillo de como rotar, trasladar y escalar objetos en rhinoceros con vbscript.
Por cierto, tambien se puede usar la función Rhino.TransformObject que usa las matrices de transformación con coordenadas homogeneas, ya escribiré algo sobre esto :).

Sub ScaleAndMove()
	Dim idBox, idBoxNew
	
	' MOVER/TRASLADAR
	idBox = DrawCube(20, 0, 0, 10)
	idBoxNew = DrawCube(20, 0, 0, 10)
	Rhino.ObjectColor idBoxNew, RGB(200, 0, 0)
	Rhino.MoveObject idBox, Array(0, 0, 0), array(0, 10, 0)
	
	'ESCALAR
	idBox = DrawCube(20, 0, 0, 10)
	Rhino.ScaleObject idBox, Array(0, 0, 0), array(0.95,0.95,0.95)
	
	' ROTAR
	idBoxNew = Rhino.RotateObject(idBox, Array(0, 0, 0), 45, array(1, 0, 0), True)
	Rhino.ObjectColor idBoxNew, RGB(200, 0, 0)
End Sub

Variant To The Power.

Ya está!, me quedo con vbVariant para implementar mis vectores, por varias razones:

– Los vectores no se pueden asignar unos a otros, me toca copiar elemento a elemento, los variant, como son variant conteniendo valores (da igual la forma) si se pueden copiar con una asignación directamente :).
– Las variant pueden cambiarse de tamaño como los vectores dinámicos, en ese momento será un vector.
– Las variant pueden contener el tipo que devuelve la función Array(lst_args) que tambien es interesante poder usarlo en cualquier momento, en ese momento sera un vector.

Afirmamos mas así que los vectores de variant y los variant que contienen vectores no son lo mismo. Sin embargo, con los variant tengo las ventajas de los dos, por ser variant puedo hacer todo lo que quiera hacer con un variant, por ser su subtipo vector dinamico puedo hacer todo lo que puedo hacer con un vector dinamico, que le den a los bytes, de momento :D.

VBScript Variant Type

Bueno, el tema es que vengo de C++ y el tipo Variant me está volviendo loco, claro si estuviera en visual basic no script le pongo tipo a todas las variables y me movería en mi salsa, pero en vbscript todas las variables son de tipo variant :). Empecemos.

Scalar Variables and Array Variables.
Las variables de tipo escalar son las variables que solo pueden contener un valor y las variables de tipo vector son las variables que pueden contener mas de un valor. Esta explicación la he sacao de la web de msdn y me ha parecido bastante interesante.

Dim radio, lado ' son variables escalares, solo podrán contener un valor
Dim sup(2) ' podrá contener 3 valores, alojados en sup(0), sup(1) y sup(2)
Dim lstObjetos() ' podrá contener los valores que yo especifique con Redim lstObjetos(tamaño)

radio = 3
sup(0) = 1
sup(1) = 2
sup(2) = "jander crander"
Redim lstObjetos(2) ' tendremos ahora posibilidad de almacenar 3 valores.

Data Types
Pues mirando los tipos de datos de las variables me encontre con que, en VBScript las variables solo pueden ser de tipo vbVariant. O sea que las variables solo pueden de tipo variante (variables variantes?? como la ensaladilla :D).
Miremos el dicccionario, una variable es algo que puede cambiar de valor y una variante es algo que puede cambiar de forma, esto ayuda algo no?. Asi que, la variables son de tipo vbVariant pero tienen subtipo, que es el tipo del valor que se le asigno, real, entero, caracter…

Mixing
Todas las variables son variant, pueden contener un valor de cualquier tipo de datos. Si ademas, declaro una variable vector, el tipo de cada elemento sera variant :).

Where is the problem then?
En la función Array(list_args), esta maravillosa función devuelve una variable variant que contiene un vector de 3 elementos que no es lo mismo que un vector de 3 variants, aunque el acceso a cada elemento en ambas variables se realiza de la misma forma.

Dim variante, estatico(2)
variante = Array(2, 2, 2)
estatico = Array(2, 2, 2) ' esto falla porque los tipos no son el mismo, aunque es toneria
' porque realmete no deja asignar un vector a otro mediante el operador asignación, hay
' copiarlos campo a campo, entonces no te das cuenta de que tipo son.

PD: si no queda claro, es porque estas cosas es mejor explicarlas en una pizarra con ejemplos, asi que
siempre podeis venir a la academia :).

Bucles 1.

Option Explicit
'Script written by 
'Script copyrighted by 
'Script version jueves, 13 de agosto de 2009 9:05:47

'Cambiar esta llamada para ir cambiando el procedimiento que ejecuta el script.
Call Main5()

Sub Main()
	Dim x
	
	x = 1
	Do While x <= 10
		Rhino.AddPoint(Array(x, 5, 0))
		x = x + 1
	Loop
	
End Sub

Sub Main2()
	Dim x, cuantosLLevo, cuantosQuiero
	
	x = 1
	cuantosQuiero = Rhino.GetInteger("Cuantos puntos dibujo?")
	cuantosLLevo = 0
	Do While cuantosLLevo < cuantosQuiero
		Rhino.AddPoint Array(x, 1, 0)
		x = x + 1
		cuantosLlevo = cuantosLLevo + 1
	Loop
End Sub


Sub Main3()
	Dim x, cuantosLLevo, cuantosQuiero
	
	x = 1
	cuantosQuiero = Rhino.GetInteger("Cuantos puntos dibujo?")
	Do While cuantosQuiero <= 0
		Rhino.Print("Disculpe. El valor debe ser positivo")
		cuantosQuiero = Rhino.GetInteger("Cuantos puntos dibujo?")
	Loop
	
	cuantosLLevo = 0
	Do While cuantosLLevo < cuantosQuiero
		Rhino.AddPoint Array(x, 1, 0)
		x = x + 1
		cuantosLlevo = cuantosLLevo + 1
	Loop
End Sub


Sub Main4()
	Dim x, cuantosLLevo, cuantosQuiero, distancia
	
	distancia = Rhino.GetInteger("Distancia entre puntos?")
	Do While distancia <= 0
		Rhino.Print("Disculpe. La distancia debe ser positiva.")
		distancia = Rhino.GetInteger("Distanca entre puntos?")
	Loop
	
	cuantosQuiero = Rhino.GetInteger("Cuantos puntos dibujo?")
	Do While cuantosQuiero <= 0
		Rhino.Print("Disculpe. El valor debe ser positivo")
		cuantosQuiero = Rhino.GetInteger("Cuantos puntos dibujo?")
	Loop
	
	cuantosLLevo = 0
	x = 1
	Do While cuantosLLevo < cuantosQuiero
		Rhino.AddPoint Array(x, 1, 0)
		x = x + distancia
		cuantosLlevo = cuantosLLevo + 1
	Loop
End Sub

Sub Main5()
	Dim x, y, d, h, numPuntos, totalPuntos

	d = Rhino.GetInteger("Distancia?")
	h = Rhino.GetInteger("Altura?")
	totalPuntos = Rhino.GetInteger("Total de puntos?")
	
	x = 1
	y = 1
	numPuntos = 0
	Do While numPuntos <= totalPuntos
		Rhino.AddPoint Array(x, y, 0)
		x = x + d
		If numPuntos Mod 2 = 0 Then
			y = 1 + h
		Else
			y = 1
		End If
		numPuntos = numPuntos + 1
	Loop
End Sub

Los procedimientos van de menos a mas complejidad. Si quereis probarlos solo
tendreis que cambiar la llamada al procedimiento.