Lexico
...el poder de lo simple...
Marzo.4.2010

Arreglos de objetos

Piénsese en el siguiente problema:
Un usuario desea que nosotros le mostremos en orden inverso  sus dos datos entrados.

La solución es trivial puesto que será suficiente con recibir los dos datos cada uno en un objeto variable y después de conocidos estos mostrarlos emitiendo primero el segundo entrado:

Tarea:
{
los objetos primero, segundo son cantidades
entre primero, segundo
muestre segundo, primero
}

Y…¿qué se haría si no fueran dos datos sino 5 ?

Haríamos algo parecido: reservamos espacio para 5 objetos variables en la RAM, luego pedimos los cinco datos por teclado y los recibimos en las cinco variables y una vez conocidos los emitimos empezando por el último recibido:

Tarea:
{
los objetos primero, segundo, tercero, cuarto, quinto son cantidades
entre primero, segundo, tercero, cuarto, quinto
muestre quinto, cuarto, tercero, segundo, primero
}

Y…¿Si no fueran 5 datos sino 150 ?

Pues haríamos algo parecido pero esta vez utilizando 150 variables diferentes.

Nótese que si al momento de diseñar el algoritmo ya conocemos el número de datos bastará con separar tantos objetos variables como sea necesario y después de entrados proceder a mostrarlos en orden inverso, así sea un tanto engorroso cuando la cantidad de ellos sea grande.

Ahora generalicemos el problema:
El usuario desea que le resolvamos el problema anterior pero ésta vez no para dos, ni para cinco, ni para 150, ni para un número ya conocido sino para una cantidad desconocida de ellos en el momento de diseñar el algoritmo:

El usuario desea que nosotros le mostremos en orden inverso  sus datos entrados.

La pregunta que surge inmediatamente es ¿En éste caso cuantos objetos variables reservamos en la RAM ?

Estamos metidos en un lío: primero que todo no conocemos tal cantidad en éste momento y sin embargo debemos programar el algoritmo ya y para hacerlo debemos definir todas las variables para conservar todos los datos sin perder ninguno de ellos hasta que llegue el último !

Un apoyo para resolver tal situación es utilizar un arreglo. Sus características principales son:

La reserva de espacio en la RAM para todos los objetos previstos del grupo se hace en una sola petición.
Todos los objetos quedan ubicados en forma adyacente dentro de un solo bloque de memoria .
Todos los objetos se identifican por con un solo nombre.
Todos los objetos son del mismo tipo o clase.
A cada objeto se le puede discriminar por la posición que ocupa dentro del grupo.
La posición es un ordinal o cantidad a la que se llama índice y puede describirse en cualquiera de las tres formas usuales: como una constante de cantidad, como una variable para cantidades o como una expresión aritmética (que al evaluarse produce una cantidad).
Una convención generalizada en muchos lenguajes de programación es asumir que la primera posición se valora con 0, la segunda con 1 y así sucesivamente. En consecuencia cuando se discrimine un objeto dentro del grupo pueden utilizarse valores para el índice en el rango válido: entre 0 y la cantidad reservada menos uno. Si se intenta acceder un elemento del arreglo con un índice por fuera del rango ocurrirá un error de lógica o una excepción y suspensión de la ejecución del programa.

Se pedirá al usuario el tamaño del grupo N y con él se crean o reservan espacios en memoria para el grupo con una sola petición (por lo tanto será un arreglo estático):

    el objeto N es una cantidad
    entre N
    los objetos Grupo[N] son cantidades



Características de los arreglos:

Todos los elementos del grupo tienen el mismo nombre.
Todos los elementos del grupo son semejantes, de la misma clase.
Están dispuestos contiguamente: físicamente vecinos en la RAM.
Se les discrimina por la posición relativa que ocupan respecto al primero del grupo.
La posición relativa es una cantidad entera. A su valor se le denomina índice.
Un índice es expresable en las tres modalidades usuales: una constante, una variable o una expresión aritmética.
Convencionalmente en muchos lenguajes de programación el índice o posición relativa que ocupa el primer elemento es el 0.
El operador de manejo indizador [ ] permite señalar o discriminar un elemento dentro del grupo:

Grupo[0] hace referencia al primer elemento del grupo
Grupo[1] hace referencia al segundo elemento
Grupo[2] ...al tercero
....

Grupo[N-1] hace referencia al último elemento del grupo.

Nótese que si han separado N espacios o elementos los índices válidos estarán en el rango 0.....N-1. Si se viola tal convención obtendrá una excepción y cancelación de la ejecución del programa.

Veamos el problema pendiente de resolver. Se reserva espacio para un grupo de tamaño dicho por el usuario final, luego se le piden uno a uno los datos y se conservan en posiciones adyacentes dentro del arreglo, finalmente se recorren las posiciones en orden inverso dentro del arreglo y se va mostrando su contenido. Nótese también que un índice en forma de una variable o una expresión, por ejemplo contador, proporciona mucha flexibilidad en el manejo del grupo de elementos.:

tarea
{
    los objetos N, contador son cantidades
    entre N
    los objetos Grupo[N] son cantidades

    copie 0 en contador
    mientras contador < N haga:
        {
        entre Grupo[contador]
        copie contador + 1 en contador
        }

    mientras contador > 0 haga
        {
        copie contador - 1 en contador
        muestre Grupo[contador]
        }
}

Ejemplo:  Una los dos puntos más alejados

tarea
{
el objeto v es una Form
el objeto bm es un bitmap (1024,768)
el objeto g es una graphics no_crear
copie Graphics.FromImage(doy bm) en g
el objeto lápiz es un pen (doy Color.Blue , doy 3)
copie "Traslado de puntos" en v.Text
v.Show

los objetos n, i, j, x1, y1, x2, y2, d, dmay son cantidades
entre n
los objetos x[n], y[n] son cantidades
copie 0 en i
mientras i<n haga
 {
 entre x[i], y[i]
 copie i + 1 en i
 }

copie 0 en i, dmay
mientras i < n haga
 {
 copie i + 1 en j
 mientras j<n haga
   {
   copie (  (x[j] - x[i])^2 + (y[j] - y[i])^2  )^(1/2) en d
   es d > dmay ?
      si:{
         copie d en dmay
         copie x[i] en x1
         copie y[i] en y1
         copie x[j] en x2
         copie y[j] en y2
         }
   copie j + 1 en j
   }
 copie i + 1 en i
 }

g.Clear(doy Color.Black)
copie 0 en i
mientras i<n haga
 {
 g.DrawEllipse(doy lápiz, doy x[i], doy y[i], doy 1, doy 1)
 copie i + 1 en i
 }
g.DrawLine(doy lápiz, doy x1, doy y1, doy x2, doy y2)
copie bm en v.BackgroundImage
muestre "Esperando para terminar"
}

Ejemplo: Mover paulatinamente los puntos del usuario hacia un punto común:

tarea
{
el objeto v es una Form
el objeto bm es un bitmap (1024,768)
el objeto g es una graphics no_crear
copie Graphics.FromImage(doy bm) en g
el objeto lápiz es un pen (doy Color.Blue , doy 3)
copie "Traslado de puntos" en v.Text
v.Show

los objetos n, c, npasos, p, xdestino, ydestino son cantidades
entre n, npasos, xdestino, ydestino
los objetos x[n], y[n], dx[n], dy[n] son cantidades
copie 0 en c
mientras c<n haga
 {
 entre x[c], y[c]
 copie (xdestino - x[c])/npasos en dx[c]
 copie (ydestino - y[c])/npasos en dy[c]
 copie c + 1 en c
 }

copie 0 en p
mientras p < npasos haga
 {
 copie p + 1 en p
 g.Clear(doy Color.Black)
 copie 0 en c
 mientras c<n haga
   {
   copie x[c] + dx[c] en x[c]
   copie y[c] + dy[c] en y[c]
   copie c + 1 en c

   g.DrawEllipse(doy lápiz, doy x[c], doy y[c], doy 1, doy 1)
   v.Refresh
   }
 copie bm en v.BackgroundImage
 muestre "paso ", p
 }

muestre "Esperando para terminar"
}

Dimensiones

Los elementos dentro de los arreglos pueden disponerse de muchas forma llamadas dimensiones. Cada dimensión permite categorizar por criterio diferente. Cada dimensión se maneja con un índice. En los ejemplos anteriores se utilizó un solo índice por lo que se le llama arreglo de una dimensión y algunos más atrevidos le llaman vector.

Cuando se usan dos índices se le llama de dos dimensiones o bidimensional o matriz por la asociación con el concepto matemático. La forma de reservar espacio en la memoria para ellos es:

                los objetos Mat[20, 10] son cantidades

y significa que reservará 200 elementos dispuestos en una estructura organizativa de 20 horizontales o filas cada una de ellas con 10 elementos. O lo que es equivalente: la organización consta de 10 verticales o columnas y en cada una de ellas hay 20 elementos.

Cuando se usan tres índices se le llama de tres dimensiones o tridimensional:

              los objetos Trid[12, 5, 6] son cantidades

reserva 360 espacio para elementos conformando el arreglo Trid de 12 horizontales, cada una con 5 columnas de profundidad 6.


Ejemplo: Producto de dos matrices

tarea
{
los objetos i, j, k, NF, NC, NCS, suma son cantidades
entre NF, NC, NCS
los objetos A[NF, NC], B[NC, NCS], C[NF, NCS] son cantidades

variando i desde 0 hasta NF-1 haga
  variando j Desde 0 hasta NC-1 haga
    entre A[i, j]

variando i desde 0 hasta NC-1 haga
  variando j Desde 0 hasta NCS-1 haga
    entre B[i, j]

variando i desde 0 hasta NF-1 haga
  variando j Desde 0 hasta NCS-1 haga
    {
    copie 0 en suma
    variando k desde 0 hasta NC-1 haga
      copie suma + A[i, k]*B[k, j] en suma

    copie suma en C[i, j]
    }

variando i desde 0 hasta NF-1 haga
  variando j Desde 0 hasta NCS-1 haga
    muestre C[i, j]
}