• Jueves 28 de Marzo de 2024, 10:29

Autor Tema:  ¿Cómo redimensionar una matriz dentro de otra matriz?  (Leído 5852 veces)

deaven

  • Miembro activo
  • **
  • Mensajes: 25
    • Ver Perfil
¿Cómo redimensionar una matriz dentro de otra matriz?
« en: Domingo 24 de Mayo de 2009, 04:03 »
0
Hola.

Tengo un problema en Visual Basic 6, quisiera ver si alguién me pdría echar una mano.

Según yo, el siguiente código sí debería de trabajar en VB6 (El código sí trabaja bien en Visual Basic 2008)

 Private Sub Matrices()
        Dim hola()
        Dim Matr()

        ReDim Preserve hola(20)
        ReDim Matr(2)

        hola(20) = Matr
        hola(20)(0) = "como"

        ReDim Preserve hola(20)(1)
 End Sub

Al ejecutar el código en VB6, me da error de sintaxis en "ReDim Preserve hola(20)(1)" ¿Cuál podría ser el problema?, ¿Hay alguna solución?

m0skit0

  • Miembro de PLATA
  • *****
  • Mensajes: 2337
  • Nacionalidad: ma
    • Ver Perfil
    • http://fr33kk0mpu73r.blogspot.com/
Re: ¿Cómo redimensionar una matriz dentro de otra matriz?
« Respuesta #1 en: Lunes 25 de Mayo de 2009, 10:17 »
0
Usa las etiquetas de código (qué cansinos sois...)  -_-

Declara el tipo de las variables  <_<

Código: Visual Basic
  1. Type tColumnas
  2.     Columnas() As Integer
  3. End Type
  4.  
  5. Dim Filas() as tColumnas
  6. Dim i As Integer
  7.  
  8. '20 filas 0 columnas
  9. ReDim Preserve Filas(20)
  10.  
  11. '20 columnas sólo en la fila 20
  12. ReDim Preserve Filas(20).Columnas(20)
  13.  
  14. '20 columnas en las 20 filas
  15. For i=0 to 20
  16.     ReDim Preserve Filas(i).Columnas(20)
  17. Next i
  18.  
No lo he probado, pero debería funcionar.

deaven

  • Miembro activo
  • **
  • Mensajes: 25
    • Ver Perfil
Re: ¿Cómo redimensionar una matriz dentro de otra matriz?
« Respuesta #2 en: Lunes 25 de Mayo de 2009, 17:02 »
0
Si k funciona, no sabía k se podía hacer eso.

Mil gracias m0skit0, me ahorraste mucho tiempo. :rolleyes:

Nebire

  • Miembro HIPER activo
  • ****
  • Mensajes: 670
    • Ver Perfil
Re: ¿Cómo redimensionar una matriz dentro de otra matriz?
« Respuesta #3 en: Lunes 25 de Mayo de 2009, 19:50 »
0
La solución que te presenta Moskito tiene una ventaja y una desventaja.

La ventaja es que te permite redimensionar FACILMENTE .
La desventaja es que el cálculo de las direcciones es más lento ya que es una matriz dentro de una matriz de estructuras. tiene que calcular la dirección del índice de la matriz luego de la estructura y luego de la otra matriz.

El modo en que VB6 redimensiona las demás dimensiones es del siguiente modo:
Código: Visual Basic
  1.  
  2. dim k()
  3.  
  4. ' declarar 3 dimensiones
  5. redim k(0 to 99, 0 to 99, 0 to 99)  ' 3 dimensiones = 100 * 100 * 100 elementos 1millón.
  6.  
  7. ' redimensionar la mariz
  8. redim preserve k(100,100, 120)
  9.  
  10. ' al utilizar preserve sólo se puede alterar la última dimensión y no permite añadir ni quitar dimensiones. Para hacer esto hay que crear una nueva matriz con las diemnsiones requeridas y pasar desde la primera hacia esta lo que deseemos, luego asignar a la primera el valor de esta.
  11.  
  12.  
  13.  

Puede interesar ver algunas consideraciones en torno alas matrices dinámicas, estáticas y el uso de preserve las matrices variant son otro caso que ahora no comentamos

Código: Visual Basic
  1.  
  2.    ' usando una matriz dinámica
  3.    Dim k() As Byte
  4.    
  5.    ' esto es perfectamente válido
  6.     ReDim k(0 To 99, 0 To 99, 0 To 99)
  7.     ReDim Preserve k(0 To 99, 0 To 99, 0 To 120)
  8.     ReDim Preserve k(0 To 99, 0 To 99, 0 To 20)
  9.    
  10.     ' esto no es válido
  11.     ReDim Preserve k(0 To 99, 0 To 99, 0 To 99, 0 To 2) ' añadir dimensiones
  12.     ReDim Preserve k(0 To 99, 0 To 99) ' quitar dimensiones
  13.     ReDim Preserve k(0 To 99, 0 To 120, 0 To 99)  ' variar tamaño de dimensiones anteriores a la última
  14.    
  15.     ' pero sin preserve (lo anterior) si es válido, porque se borra toda la información de la matriz y se crea de nuevo, por eso se llama dinámica
  16.     ReDim k(0 To 99, 0 To 99, 0 To 99, 0 To 2)  ' añadir dimensiones
  17.     ReDim k(0 To 99, 0 To 99)  ' quitar dimensiones
  18.     ReDim k(0 To 99, 0 To 120, 0 To 99)   ' variar tamaño de dimensiones anteriores a la última
  19.    
  20.    ' usando una matriz estática
  21.     Dim W(0 To 99, 0 To 99) As Byte
  22.  
  23.     ' no se puede redimensionar de ninguna manera, W es una matriz estática, durante su vida no puede tener otras dimensiones que las declaradas, es una matriz de dimensiones 'constante'
  24.     ReDim Preserve W(0 To 99, 0 To 120) ' en cuanto entre en la función marcará el error (early binding), comentar la línea entonces
  25.     ReDim W(0 To 99, 0 To 120) ' en cuanto entre en la función marcará el error (early binding), comentar la línea entonces
  26.  
  27.     w(45, 45, 45) = 122  ' marcará que las dimensiones no corresponden... en cuanto entre en la función (early binding)
  28.     k(45, 45, 45, 45, 45, 45) = 122  ' aquí sólo notará el error cuando llegue a su ejecución. (late binding)
  29.    
  30.     ' esto no da error, porque al ser estática con erase lo que hace es borrar la matriz y reconstruirla nuevamente (equivale a borrar su contenido a cero, una reiniciación de la misma)
  31.     Erase W
  32.     W(45, 45) = 122
  33.    
  34.     ' una matriz dinámica borrada equivale a no estar inicializada es como cuando sólo se había declarado Dim k() As Byte
  35.     ' aquí dará error, el error es que no tiene dimensiones declaradas.
  36.     Erase k
  37.     k(45, 45, 45) = 122
  38.  
  39.  

ejemplo de un redimensionado de una matriz dinámica en una dimensión anterior:
Supongamos una matriz que guarda meses y días en forma de matriz...
Código: Visual Basic
  1.  
  2.    dim año() as boolean
  3.   redim año(1 to 12, 1 to 7)  ' primera semana de cada mes
  4.  
  5.   ' asignar valores...
  6.    for mes= 1 to 12
  7.        for dia=1 to 7
  8.          año(m,s)=true
  9.      next
  10.   next
  11.  
  12.  

Después de esto supongamos que tenemos otro problema similar pero que en vez de usar sólo la 1ª semana de cada mes queremos usar las 4 semanas completas del mes para redimensionar la matriz
podríamos considerarlo como 28 días en vez de 7


Código: Visual Basic
  1.  
  2.    redim año(1 to 12, 1 to 28)  'las 4 semanas de cada mes
  3.  
  4.   ' asignar valores...
  5.    for mes= 1 to 12
  6.        for dia=8 to 28
  7.          año(m,s)=true
  8.      next
  9.   next
  10.  
  11.  

pero puede que queramos trabajar utilizando una dimensión más para referirnos a cada semana por separado dado que no podemos hacer un preserve y a la vez variar el número de dimensiones tenemos que utilizar una mtriz de intercambio...


Código: Visual Basic
  1.  
  2. dim prov(1 to 12, 1 to 4, 1 to 7) ' declaramos la matriz provisional que es como debería quedar la matriz original
  3.    
  4.   ' asignamos los datos actuales ' hacemos un equivalente al preserve pero trasladando datos donde corresponda
  5.   for mes= 1 to 12
  6.        for dias= 1to 7
  7.             prov(mes,1,dias)= año(mes,dias)
  8.       next
  9.  next
  10.  
  11. ' si queremos reasignar los datos nuevos...
  12.      for mes= 1 to 12
  13.          for semana= 2 to 4
  14.            for dias= 1to 7
  15.                prov(mes,semana,dias)= true
  16.           next
  17.      next
  18.  next
  19.  
  20. ' finalmente la matriz se la entregamos a la matriz de uso público aquí prov es privada para la función cuyo cometido exclusivo (de la función) podría ser éste
  21.    año= prov  ' año toma tanto los datos como las diemsniones,
  22.  
  23.  

Esto (lo anterior) supone una molestia porque se necesita crear una función específicamente para esto, por eso la solución que expone Moskito debe tenerse en consideración.

Otra solución es la que te presento a continuación, que trata de usar una matriz dinámica unidimensional oculta, el sistema utilizado para localizar el valor es similar a como se hace a bajo nivel, pero de cara a usarlo repetidamente es más cómodo que utilizar una matriz de varias dimensiones que además se prestan mucho a confusión. De hecho cuand se usan más de 2 dimensiones interesa más tener un estructura de este tipo. De hecho con poco más lo puedes convertir en una clase

Redimensionar la matriz equivale a asignar a la propiedad año un nuevo valor. Y tomar el valor de ún índice  equivale a usar la propiedad DiaX donde se le pasan los indices de cada dimensión mes,semana y dia que se utiliza para calcular el índice de la matriz valores.

Código: Visual Basic
  1.  
  2.    public type infoAño
  3.        Meses as byte
  4.        Semanas as byte
  5.        Dias as byte
  6.    end type
  7.    
  8.     private p_Año as infoAño
  9.  
  10.    '  la matriz es unidimensional, es ella quien guarda todos los elementos y somos nosotros quienes proveemos la dirección de cada elemento.
  11.    Private valores() as boolean
  12.  
  13.      ' pregunta por los índices que tiene cada 'dimensión'
  14.     friend property get Año( optional preservar as boolean=false) as infoAño
  15.        año= p_año
  16.     end property
  17.         ' redimensiona la matriz privada con los nuevos valores de las diemsniones
  18.        friend property let Año( optional preservar as boolean=false, byref nAño  as infoAño)
  19.             if preservar=false then
  20.                   redim valores(0 to (nAño.meses  * nAño.seamanas * nAño.dias ) - 1)
  21.             else
  22.                  ' invocar a una función que resguarde valores actuales .. queda como ejercicio para el interesado,
  23.                  ' esto puede ser en parte similar a la función del código anterior pero debería usarse un select case para ver que 'dimensiones' son las que varían
  24.            end if
  25.            p_año= nAño
  26.        next
  27.    
  28.      public property get DiaX(byval Mes as byte, byval Semana as byte, byval Dia as byte) as boolean
  29.              diaX= valores((mes-1) * 28) + ((semana-1) * 7) + dia - 1)
  30.       end property
  31.           public property let DiaX(byval Mes as byte, byval Semana as byte, byval Dia as byte, byval v as boolean)
  32.                    valores((mes-1) * 28) + ((semana-1) * 7) + dia - 1)= v
  33.            end property
  34.  
  35.     ' sobrecarga, llama a la propiedad, pero recibe como parámetro una estructura....
  36.     friend function GetDiaX(byref fecha as infoAño) as boolean
  37.           GetDiaX= diax(fecha.meses, fecha.semanas,fecha.dias)
  38.     end function
  39.     friend sub SetDiaX(byref fecha as infoAño)
  40.           diax=(fecha.meses, fecha.semanas,fecha.dias)
  41.     end function
  42.  
  43.  
  44.  
nota: el código está escrito directamente quizás se haya escapado algún error
nota2: para los que se toman todas las palabras al pie de la letra... el hecho de utilizar variables llamadas mes, semana ,etc... sólo tiene por objeto no perderse en detalles por trabajar con objetos de naturaleza abstracta, si un ejemplo se explica con algo conocido resulta más fácil ver lo que se quiere explicar sin perderse en la naturaleza del objeto de ejemplo si fuera bastracto, por tanto en ejemplos de este tipo sólo interesa la didáctica. Como todo el mundo sabe como el año no tiene períodos regulares lo que supuestamente se utiliza para el cálculo en el ejemplo no tiene nada que ver con el cálculo real de fechas, si a alguien le confunde, sustituye mes, semana, dia y año por nombres cualquiera de variables..

En todo caso haz unas pruebas de rendimiento con cada método si tienes que hacer un uso intensivo para decidir el que más convenga... si no hay un uso intensivo y por tanto el rendimiento no es decisivo, elige el que más cómodo te resulte.
«Ma non troppo»
----> ModoVacaciones = False<----

deaven

  • Miembro activo
  • **
  • Mensajes: 25
    • Ver Perfil
Re: ¿Cómo redimensionar una matriz dentro de otra matriz?
« Respuesta #4 en: Martes 26 de Mayo de 2009, 06:13 »
0
Hola Nebire, muchas gracias x tu respuesta
Exactamente estoy viendo lo k comentas del rendimiento de lo k Moskito me hizo el favor de contestarme.
Para el programa k estoy optimizando y ampliando, es muy importante la velocidad, y como éste usa, en buena medida, muchas matrices (algunas matrices se redimensionan miles de veces, x cuestión de compromiso entre velocidad y memoria usada), es imprescindible k escoja el sistema más veloz.

Muy interesante tu explicación k das del funcionamiento de las matrices
El método de sustitución del uso de matrices k me comentas me parece también muy interesante. Estoy haciendo las pruebas de rendimiento k comentas tanto de lo comentado por Moskito como lo comentado x tí. Si alguno de esos métodos son más rápidos k los k actualmente uso, sin duda los implementaré, especialmente en la ampliación del programa, porque para lo ya escrito del programa me sería algo tardado, x k son miles de líneas de código k se tendrían k modificar.

Para k te des una idea mas amplía, pongo la sub, k mando llamar para redimensionar varios tipos de matriz al doble de índices k tenga su dimensión última. Indicando entre líneas de asteríscos los puntos k quiero optimizar .


'Nebire, nuevamente gracias x el valioso tiempo k te tomas en contestar, analizaré el código k escribiste a fondo.

Saludos

Código: Visual Basic
  1.  
  2. 'Redimensiona los índices de la matriz al doble de su valor actual, preservando sus valores originales (incluye matrices de una dimensión, 2 dimensiones y matrices dentro
  3.     'de matrices)
  4. Public Sub RedimMat(NombreMatriz As String, Optional Nivel1, Optional Nivel2, Optional LlenarLosNuevosIndicesConElSigValor As Boolean = False, _
  5.                 Optional ValorAIntroducirEnLosIndicesDeLaMat As Variant = SinVal)
  6. 'ENTRADAS
  7. '1)NombreMatriz indica el nombre de la matriz a redimensionar
  8. '2)Nivel1 = Primer nivel de profundidad de matriz
  9. '3)Nivel2 = Segundo nivel de profundidad de matriz
  10. '4)ValorAIntroducirEnLosIndicesDeLaMat = Es el valor k se va a introducir en los nuevos índices redimensionados de la matriz (en caso de k LlenarLosNuevosIndicesConElSigValor
  11.     '= True
  12. '5)LlenarLosNuevosIndicesConElSigValor = Bandera para utilizar ValorAIntroducirEnLosIndicesDeLaMat o no utilizarla
  13.  
  14. 'SALIDAS
  15. '1)La matriz indicada x el NombreMatriz, ya redimensionada al doble
  16.  
  17. Static MatRedimMatTemporal As Variant
  18. Dim EmpezarALlenarConElValor3APartirDeEsteNumero
  19. Dim NumeroLlenando As Long
  20.  
  21. Select Case NombreMatriz
  22.     'Matrices con 1 dimensión
  23.     Case "CPsValores"
  24.         ReDim Preserve CPsValores(LBound(CPsValores) To UBound(CPsValores) + (UBound(CPsValores) _
  25.         - LBound(CPsValores) + 1))
  26.     Case "MatDendDsAMover"
  27.         ReDim Preserve MatDendDsAMover(LBound(MatDendDsAMover) To UBound(MatDendDsAMover) + (UBound(MatDendDsAMover) _
  28.         - LBound(MatDendDsAMover) + 1))
  29.     Case "MatrizDeCamSeñales"
  30.         ReDim Preserve MatrizDeCamSeñales(LBound(MatrizDeCamSeñales) To UBound(MatrizDeCamSeñales) + (UBound(MatrizDeCamSeñales) _
  31.         - LBound(MatrizDeCamSeñales) + 1))
  32.     Case "PoblacsPendientes"
  33.         ReDim Preserve PoblacsPendientes(LBound(PoblacsPendientes) To UBound(PoblacsPendientes) + (UBound(PoblacsPendientes) - LBound(PoblacsPendientes) + 1))
  34.     Case "C"
  35.         ReDim Preserve C(LBound(C) To UBound(C) + (UBound(C) - LBound(C) + 1))
  36.     Case "MatCamSeñalesDeCaseta"
  37.         ReDim Preserve MatCamSeñalesDeCaseta(LBound(MatCamSeñalesDeCaseta) To UBound(MatCamSeñalesDeCaseta) + (UBound(MatCamSeñalesDeCaseta) - LBound(MatCamSeñalesDeCaseta) + 1))
  38.     Case "MatDeCaHisYCaMas"
  39.         ReDim Preserve MatDeCaHisYCaMas(LBound(MatDeCaHisYCaMas) To UBound(MatDeCaHisYCaMas) + (UBound(MatDeCaHisYCaMas) - LBound(MatDeCaHisYCaMas) + 1))
  40.    
  41. '*********************************************************************
  42.     'PUNTO K QUISIERA OPTIMIZAR
  43.     'Matrices q a fuerzas se tienen q copiar a una matriz individual, porque la instrucción Redim no permite redimensionarlas directamente, porque
  44.         'son matrices q están dentro de otra matriz, y vb6 no la reconoce como tal (visual basic 2008 sí la reconoce)
  45.     Case "C() () "
  46.         MatRedimMatTemporal = C(Nivel1)(Nivel2)
  47.         If LlenarLosNuevosIndicesConElSigValor = True Then EmpezarALlenarConElValor3APartirDeEsteNumero = UBound(MatRedimMatTemporal) + 1
  48.         ReDim Preserve MatRedimMatTemporal(LBound(MatRedimMatTemporal) To UBound(MatRedimMatTemporal) + (UBound(MatRedimMatTemporal) _
  49.         - LBound(MatRedimMatTemporal) + 1))
  50.         If LlenarLosNuevosIndicesConElSigValor = True Then
  51.             For NumeroLlenando = EmpezarALlenarConElValor3APartirDeEsteNumero To UBound(MatRedimMatTemporal)
  52.                 MatRedimMatTemporal(NumeroLlenando) = ValorAIntroducirEnLosIndicesDeLaMat
  53.             Next
  54.         End If
  55.         C(Nivel1)(Nivel2) = MatRedimMatTemporal
  56.     Case "CpsValores() () "
  57.        
  58.         MatRedimMatTemporal = CPsValores(Nivel1)(Nivel2)
  59.         If LlenarLosNuevosIndicesConElSigValor = True Then EmpezarALlenarConElValor3APartirDeEsteNumero = UBound(MatRedimMatTemporal) + 1
  60.         ReDim Preserve MatRedimMatTemporal(LBound(MatRedimMatTemporal) To UBound(MatRedimMatTemporal) + (UBound(MatRedimMatTemporal) _
  61.         - LBound(MatRedimMatTemporal) + 1))
  62.         If LlenarLosNuevosIndicesConElSigValor = True Then
  63.             For NumeroLlenando = EmpezarALlenarConElValor3APartirDeEsteNumero To UBound(MatRedimMatTemporal)
  64.                 MatRedimMatTemporal(NumeroLlenando) = ValorAIntroducirEnLosIndicesDeLaMat
  65.             Next
  66.         End If
  67.         CPsValores(Nivel1)(Nivel2) = MatRedimMatTemporal
  68. '***********************************************************************
  69.  
  70.     'Matrices con 2 dimensiones
  71.     Case "MatCamLlavesTratadas"
  72.         ReDim Preserve MatCamLlavesTratadas(LBound(MatCamLlavesTratadas, 1) To UBound(MatCamLlavesTratadas, 1), _
  73.         LBound(MatCamLlavesTratadas, 2) To UBound(MatCamLlavesTratadas, 2) + (UBound(MatCamLlavesTratadas, 2) - LBound(MatCamLlavesTratadas, 2) + 1))
  74.        
  75.        
  76.     Case "MatSeparadoresDeConceptos"
  77.         ReDim Preserve MatSeparadoresDeConceptos(LBound(MatSeparadoresDeConceptos, 1) To UBound(MatSeparadoresDeConceptos, 1), _
  78.         LBound(MatSeparadoresDeConceptos, 2) To UBound(MatSeparadoresDeConceptos, 2) + (UBound(MatSeparadoresDeConceptos, 2) - LBound(MatSeparadoresDeConceptos, 2) + 1))
  79.    
  80.     Case "MatrizDeAccionesEnVisio"
  81.         ReDim Preserve MatrizDeAccionesEnVisio(LBound(MatrizDeAccionesEnVisio, 1) To UBound(MatrizDeAccionesEnVisio, 1), _
  82.         LBound(MatrizDeAccionesEnVisio, 2) To UBound(MatrizDeAccionesEnVisio, 2) + (UBound(MatrizDeAccionesEnVisio, 2) - LBound(MatrizDeAccionesEnVisio, 2) + 1))
  83.        
  84.     Case "MatDeCaHis"
  85.         ReDim Preserve MatDeCaHis(LBound(MatDeCaHis, 1) To UBound(MatDeCaHis, 1), _
  86.         LBound(MatDeCaHis, 2) To UBound(MatDeCaHis, 2) + (UBound(MatDeCaHis, 2) - LBound(MatDeCaHis, 2) + 1))
  87.    
  88.    
  89.     Case Else
  90.     ErrorCritico ("La Matriz se tiene que redimensionar antes de continuar"), -1: Debug.Assert Seguir: Ending 'Si no encontré el NombreMatriz, saca un error y ya no puedo
  91.         'continuar hasta k solucione el error.
  92.    
  93.    
  94.    
  95. End Select
  96.  
  97.  
  98. NombreMatriz = ""
  99.  
  100. End Sub
  101.  
  102.  
  103.  
  104.  
  105.  

m0skit0

  • Miembro de PLATA
  • *****
  • Mensajes: 2337
  • Nacionalidad: ma
    • Ver Perfil
    • http://fr33kk0mpu73r.blogspot.com/
Re: ¿Cómo redimensionar una matriz dentro de otra matriz?
« Respuesta #5 en: Martes 26 de Mayo de 2009, 12:07 »
0
Nebire, como siempre, me quito el sombrero  ;)  :good:

Por cierto, deaven, si te interesa calcular el tiempo que tarda en ejecutarse una parte del código, te aconsejo que le eches un vistazo a esto, seguro que te viene muy bien (porque yo también lo tuve que hacer :)):

Código: Visual Basic
  1. Private Declare Function timeGetTime Lib "winmm.dll" () As Long  
  2.  
  3. Private Sub TalyCual(ByLoQueSea Parametro As TipoLoQueSea)
  4.     Dim Tiempo_Inicial As Long
  5.    
  6.     Tiempo_Inicial = timeGetTime()
  7.    
  8.     'Procesamos...
  9.  
  10.     Debug.Print timeGetTime - Tiempo_Inicial
  11. End Sub
  12.  
Ah y otro consejo: evita el uso de cadenas de caracteres todo lo que puedas. La lentitud de su procesamiento es uno de los mayores defectos de VB6  :bad:

Saludos y espero que te sirva

Nebire

  • Miembro HIPER activo
  • ****
  • Mensajes: 670
    • Ver Perfil
Re: ¿Cómo redimensionar una matriz dentro de otra matriz?
« Respuesta #6 en: Jueves 28 de Mayo de 2009, 04:59 »
0
Deaven debes tener en cuenta algunas cosillas para acelerar tanto  trasiego.
Si como dices una matriz de repente tienes que aumentarla al doble de su tamaño, entiendo que o bien haces un trasvase de información procedente de dos matrices de idéntico tamaño, o bien entiendo que estás reservando espacio de una sola vez para que no se agote rápidamente y tengas contínuamente que que redimensionar las matrices. Si esto es así, es posible que te vaya mejor una colección.

Una matriz es más rápida que una colección cuando el número de elementos no va a superar nunca algo así como 100 a partir de ese tamaño una colección suele ser más eficiente, añades y quitas elementos dinámicamente por lo que no malgastas memoria, esto es no utilizas más espacio del que justamente necesitas a cada instante.

Ahora bien una colección es un poco limitada, no permite muchas cosas, sin embargo puedes utilizarla para crear clases que utilicen la colección como base añadiendo métodos.

No obstante si (como supongo) el código lo estás usando para el programa de inteligencia artificial,  creo que sería más acertado que en determinadas circunstancias usaras árboles. en VB6 es relativamente fácil implementar cualquier tipo de árbol. Por ejemplo posiblemente te sería muy útil el arbol de tipo 'montículos' ya que supongo que muchas de las acciones que realices se basarán en cuestiones de prioridad. Los montículos también son óptimos para ordenar y además los montículosm permiten pasarlo a una matriz o crear un montículo desde una matriz en un tiempo prácticamente lineal.

Es difícil determinar que tipo de árbol irá mejor para cada cosa, porque desconocemos los detalles del uso que le das a cada matriz.

En cualquier caso si usas matrices ten en cuenta el siguiente consejo:
Cuando utilices varias veces seguidas el mismo índice de una matriz es más rápido usar una variable. Pongo un ejemplo y lo pruebas si te parece...

Código: Visual Basic
  1.  
  2.     dim k as long,  valor as long
  3.     dim Matriz(0 to (10^6) -1) as long
  4.     dim o as long, p as long, q as long, r as long
  5.    
  6.     dim t1 as siongle, t2 as single  ' cronómetros...
  7.  
  8.     ' asignamos valores a la matriz para empezar, no importa el valor para lo que queremos mostrar.
  9.    for k= 0 to ubound(matriz)
  10.          matriz(k)=k
  11.     next
  12.    
  13.     t1= timer
  14.     for k= 0 to ubound(matriz)
  15.          o=matriz(k) / 3
  16.          p= matriz(k) mod 11
  17.          q= matriz(k) + 5
  18.          if matriz(k) mod 25=0 then
  19.                  r= matriz(k) - q
  20.          else
  21.                 r= matriz(k) - p
  22.          end if
  23.     next
  24.     t1= timer - t1
  25.  
  26.     t2= timer
  27.     for k= 0 to ubound(matriz)
  28.         valor= matriz(k)
  29.          o=valor / 3
  30.          p= valor mod 11
  31.          q= valor + 5
  32.          if valor mod 25=0 then
  33.                  r= valor - q
  34.          else
  35.                 r= valor - p
  36.          end if
  37.     next
  38.     t2= timer - t2
  39.     msgbox "tiempo 1: " & t1 & " tiempo 2: " & t2
  40.  
  41.  


Fíjate que el código es equivalente y que la segunda parte es más larga pués incluye una asignación más al principio del bucle. sin embargo correrá más rápido, porque primero investiva la dirección de la matriz 'matriz(0)' y luego necesita localizar el índice 'x' en la matriz el cálculo claramente es : dirección elemento 0 + desplazamiento indice = matriz(0) + (indice * bytes que ocupa el tipo usado).
Como en el bucle se usa matriz(k) 5 veces en cada ciclo es más lento que el 2º ejemplo que sólo utiliza 1 vez, luego recurre a una variable cuya dirección se toma sin calcular nada (*), lo que en grandes bucles o en un uso intensivo de matrices supone un buen ahorro de tiempo. Básicamente si usamos un mismo índice al menos 4 o más veces el tiempo de hacer una asignación a una variable 'nueva' compensa al uso de calcular la dirección del índice.
«Ma non troppo»
----> ModoVacaciones = False<----

deaven

  • Miembro activo
  • **
  • Mensajes: 25
    • Ver Perfil
Re: ¿Cómo redimensionar una matriz dentro de otra matriz?
« Respuesta #7 en: Jueves 28 de Mayo de 2009, 09:17 »
0
Hola
M0skit0 , Nebire, muchas gracias x sus consejos.

Nebire, efectivamente el dobleteo de espacio en las matrices lo hago para reservar espacio de una sola vez, pero no mucha para no agotarla y que me permita redimensionar la menor cantidad de veces posibles.
Te comento k al principio de la elaboración del programa escogí usar colecciones, pero noté k, en el caso concreto para lo k las uso, era muchísimo más rápido utilizar matrices, x lo k en determinado momento tuve k hacer el cambio casi completo de colecciones a matrices. De hecho, en el caso concreto de mi programa, solo en un caso resultó más eficiente utilizar las colecciones k las matrices .

Como te habrás dado cuenta, soy un programador bastante novato, y no conocía los árboles k mencionas, estuve investigando un poco k erán, y te comento, k por lo k entendí, sin saberlo, actualmente ya he implementado algo un poco parecido a esos árboles.

Nebire, muchas gracias x el código, me quedó muy clara tu explicación.

Y Oigan, sinceramente les reitrero mi agradecimiento x sus comentarios y consejos. :good:

Saludos

Nebire

  • Miembro HIPER activo
  • ****
  • Mensajes: 670
    • Ver Perfil
Re: ¿Cómo redimensionar una matriz dentro de otra matriz?
« Respuesta #8 en: Lunes 1 de Junio de 2009, 04:10 »
0
Cita de: "deaven"
Te comento k al principio de la elaboración del programa escogí usar colecciones, pero noté k, en el caso concreto para lo k las uso, era muchísimo más rápido utilizar matrices, x lo k en determinado momento tuve k hacer el cambio casi completo de colecciones a matrices. De hecho, en el caso concreto de mi programa, solo en un caso resultó más eficiente utilizar las colecciones k las matrices .
Deaven, si esta afirmación es cierta, es bastante probable que estés produciendo código 'espagueti'.

Un modo de determinarlo a grsosso modo es confirmar que, el hecho de que tus matrices trabajen más rápido que las colecciones no sea debido a:
a )  que sólo has considerado el tiempo de acceso a los elementos.
b ) que la operación de acceso a los elementos es sustancialmente más elevada proporcionalmente en realación a otras operaciones como añadir o eliminar elementos de la matriz.

Si es el caso a, estás producinedo código espagueti, si señalas el caso b, como, sin embargo señalabas que tienes que redimensionar miles de veces muchas matrices resulta una contradición.
Para considerar el rendimiento de una estructura no debe sólo considerarse el tiempo de acceso a los elementos, en esto una matriz es más rápido que el resto de estructuras, también debe considerarse el tiempo invertido en el resto de operaciones realizadas sobre la estructura, típicamente añadir y quitar elementos y buscar elementos determinados.

Si las matrices son los reyes en cuanto al acceso a un eleento arbitrariamente escogido no lo resulta para acceder a un determinado elemento que cumpla un criterio, por ejemplo si digo devolver el valor que sigue al que yace en el elemento x, en una matriz requiere recorer toda la matriz para buscar y verificar que el elemento hallado sea el que cumple dicho objetivo, si la matriz tiene 1 millón de elementos significa que debes recorrer 1 millón de elementos, si se emplea una estructura cuyos elementos están ordenados sólo se necesitan recorrer  20 elementos para obtener el resultado.

Igualmente añadir o quitar elementos , si a la matriz la redimensionas cada vez que añades o eliminas un elemento es lento, y no tanto si el elemento añadido o eliminado es el último que si es el primero, como según los casos no va a ser siempre el último elemento significa que si tienes 1 millón de elementos y tengo que eliminar el elemento 500.000 significa que tengo que bajar desde el elemento 500.001 hasta el final -1 una posición y luego redimensionar (aunque no estás obligado a redimensionar en un momento dado). En eso las matrices son muy lentas. Un árbol por ejemplo añade o elimina elementos en cualquier posición con mucha celeridad. Basta con conectar los hijos del nodo a eliminar (si sólo vamos a eliminar ese nodo, y no también su rama de descendencia) con el padre del nodo a eliminar, de acuerdo al tipo de árbol que sea sólo conectaremos uno de sus hijos o varios y si el árbol mantiene un tipo de orden deba seleccionarse el hijo que se conecta al padre si sólo se conecta 1...

En fin, que si estás trabajando con un programa para inteligencia artificial te recomiendo encarecidamente que diseñes varios tipos de estructuras de datos (empleando clases) para hacer un código mucho más fácil de mantener y sobretodo de ampliar reducirás drásticamente las líneas de código necesarias y globalmente correrá más rápido, incluso aunque alguna clase se base en utilizar una matriz cuando su tamaño nunca sea relativamente grande...( creo que tenía por ahí un código que me pidió mi sobrino sobre un simple colección realizada usando una matriz, la condición de uso de esa clase le sugerí que no superara como máximo los 100 elementos, si lo quieres me lo dices lo localizo y te lo expongo). A base de matrices un programa complejo se vuelve insostenible y cada vez que decidas modificarlo te dará una pereza enorme porque tendrás que 'ponerte las pilas'  para entender tu propio código (qué quería hacer aquí..) y ver donde debes añadir y cómo sin afectar lo que ya está hecho...
«Ma non troppo»
----> ModoVacaciones = False<----

deaven

  • Miembro activo
  • **
  • Mensajes: 25
    • Ver Perfil
Re: ¿Cómo redimensionar una matriz dentro de otra matriz?
« Respuesta #9 en: Lunes 1 de Junio de 2009, 08:09 »
0
Hola Nebire

Te comento algunas de las particularidades de dos de las matrices k uso en el programa.

MATRIZ C
Esta matriz es la principal, tiene una vida permanente y consume casi alrededor del 90% de la memoria usada)
Esta matriz tiene 3 niveles de profundidad matricional -el formato es: C (Nivel1)(Nivel2)(Nivel3).
Si echas un vistazo a la sub RedimMat, verás k solo redimensiono los índices del Nivel1 y del Nivel3 de esa Matriz C.
Para el Nivel1, una vez creados índices extras (mandar a Redim), jamás cambiarán sus elementos (no los borraré, ni los intercambiaré, creo k esto es importante para escoger utilizar matrices en lugar de Colecciones).

Para el caso del Nivel3, una vez creados índices extras, también jamás se borrarán los elementos k contiene, pero sí se reacomodarán frecuentemente en pares, pe. si el contenido del índice 150, se colocará en el índice 100, entonces el contenido del índice 100, se colocará en el índice 150 -debido a esto, en ningún momento tengo k bajar todos los elementos k estén arriba de uno de los elementos movidos-. Creo k aquí también es preferible utilizar matrices en lugar de Colecciones.


MATRIZ CPsValores
Esta matriz es muy parecida a la matriz C (3 niveles de profundidad matricional), excepto en k consume alrededor del 50% del tiempo de proceso del CPU, se crea  y se destruye constantemente.
Con esta matriz, sí k tengo grandes problemas de uso de CPU. Y pienso k es debido a k escogí erróneamente una matriz.
Debido a esa mala elección, si introduzco alrededor de 1000 páginas de conversación al programa, empiezo a tener problemas de tiempo excesivo del proceso de la información, debido a k frecuentemente tengo k eliminar algún índice del nivel1  y luego bajar un lugar a todos los índices k estén arriba del eliminado, y pues me consume muchísimo tiempo.

He pensado en algunas soluciones a ésta última situación (además de la de los árboles k me comentas) , k lamentablemente hasta la amplicación del programa podré implementar (...la novatez se paga).

Y sí, sin duda, la utilización de matrices de varias profundidades ha vuelto la depuración del programa, excesivamente tardado y complejo (ayer mismo, para hacer una sola nueva implementación k involucraba a todo el programa, me tardé toda la noche -...mmmm o será k ya estoy demasiado usado jaja  :hitcomp:  ,
pero...bueno, creo k el fin hará k valga la pena :rolleyes:  )

Nuevamente Gracias x tus comentarios y sugerencias.

Saludos