Recientemente, implementando una función he dado con un algoritmo muy sencillo que a lo mejor puede ser de utilidad para alguno de vosotros. Se trata del siguiente:
- Code: Select all Expand view
- nPos := Int( ( nItem + nTama - 1 ) / nTama )
Al que he llamado nItemPos(), y que se puede implementar, en su forma preprocesada:
- Code: Select all Expand view
- #translate nItemPos( <nVar1>, <nVar2> ) => Int( ( <nVar1> + <nVar2> - 1 ) / <nVar2> )
¿Para qué sirve? Tiene 2 posibles aplicaciones:
1º - Dado un conjunto de elementos, numerados correlativamente, y agrupados en subconjuntos de igual tamaño, permite determinar en qué subconjunto se haya un elemento determinado.
- Code: Select all Expand view
- Ejemplo 1: dado el conjunto de los meses, numerados del 1 al 12, si los agrupamos por trimestres, podemos saber a qué trimestre pertence un mes determinado.
Agosto = 8
Trimestre = nItemPos(Agosto,3) // RESULTADO: 3º trimestre.
Si los agrupamos en cuatrimestres:
Cuatrimestre = nItemPos(Agosto,4) // RESULTADO: 2º cuatrimestre.
- Code: Select all Expand view
- Ejemplo 2: Si tenemos un conjunto de 96 elementos que representamos en pantalla agrupados en 8 columnas de 12 elementos.
Numerados por columnas, podemos saber en que columna estará el elmento nº 57:
01 13 25 37 .. 85
02 14 26 38 .. 86
03 15 27 39 .. 87
04 16 28 40 .. 88
.. .. .. .. .. ..
nCol = nItemPos(57,12) // RESULTADO: 5ª columna.
Numerados por filas, podremos saber en que fila estará el elmento nº 57:
01 02 03 04 .. 08
09 10 11 12 .. 16
17 18 19 20 .. 24
25 26 27 28 .. 32
.. .. .. .. .. ..
nFila = nItemPos(57,8) // RESULTADO: 8ª fila.
- Code: Select all Expand view
- Ejemplo 3: Si tenemos un Listbox cuyo panel mide 667 pixels de alto y cada linea mide 23 pixels de grosor (incluyendo margenes, contenido y grid), podemos saber, cuando pinchamos con el ratón sobre el pixel nRow = 133, sobre qué línea del Listbox hemos pinchado.
nLinea = nItemPos(133,23) // RESULTADO: 6ª línea
Aquí tengo que tener que hacer un pequeño inciso: se supone que el listbox tiene un contorno (por ejpmlo 1 pixel) y una cabecera (por ejmplo 37 pixel), esos pixels hay que restarlos a nRow porque el primer pixel de la primera línea empieza en el pixel número 38, no en el 0. Por lo que en realidad la línea sobre la que hemos pinchado con el ratón sería la:
- Code: Select all Expand view
- nLinea = nItemPos(133-38,23) // RESULTADO: 5ª línea
Sólo hay que tener en cuanta que todos los subconjuntos deben tener la misma cantidad de elementos, salvo el último que puede ser inferior (no superior)
- Code: Select all Expand view
- Ejemplo 4: Tenemos 28 personas montadas en 6 vehículos con capacidad para 5 personas cada uno. Habrá 5 autos con 5 personas cada uno, más un 6º vehículo con sólo 3 viajeros. Si le asignamos un número a cada persona (ordanada y correlativamente), podremos saber en qué vehículo viaja el 11º pasajero:
nAuto = nItemPos(11,5) // RESULTADO: 3º vehículo
Lógicamente no tenemos necesidad de saber en que vehículo estará el pasajero número 30, porque sólo hay 28 personas, pero si me dirá que el 28º pasajero esta el coche número 6 (que no está completo). Luego, puedo ubicar todos y cada uno de los elementos existentes aunque el último subconjubto no esté lleno. Esto me lleva a la segunda posible utilidad de nItemPos().
2º - Dado un número de elementos cualquiera, me permite determinar cuantos subconjuntos de x elementos se pueden formar con ellos. Puede que el último de esos subconjuntos no esté completo, pero a efectos prácticos, se trata del ultimo subconjunto necesario para ubicar a todos y cada uno de los items sin que se quede ninguno fuera del sistema.
- Code: Select all Expand view
- Ejemplo 5: Siguiendo con el ejemplo de los vehículos. Si tengo 37 pasajeros y tengo que transportarlos en vehículos con capacidad para 5 personas cada uno. ¿Cúantos autos necesitaré?
nAutos = nItemPos(37,5) // RESULTADO: 8 vehículos. (7 llenos y uno con 2 personas)
- Code: Select all Expand view
- Ejemplo 6: Retomando nuestro Listbox. Hemos dicho que el panel mide 667 pixels de alto, 628 sin cabecera ni bordes superior e inferior, y que cada línea ocupa 23 pixels. ¿Cúantas líneas van a caber?
nLineas = nItemPos(628,23) // REULTADO: 28 líneas (27 completas más otra parcialmente escondida)
Si sólo vamos a pintar las líneas completas bastaría con hacer: Int(622/23)
Podemos saber el espacio sobrante:
nPixels = (nItemPos(628,23)*23)-628 // RESULTADO: 16 pixels se quedan fuera
nPixels = 628-(Int(628/23)*23) // RESULTADO: 7 pixels se quedan dentro
- Code: Select all Expand view
- Ejemplo 7: Si el panel del Listbox mide 937 pixels de ancho (sin bordes), podemos saber cuantos columnas de 173 pixels me van a caber:
nCols = nItemPos(967,173) // RESULTADO: 6 (5 de 173 pixel más la última de sólo 102 pixels)
Como verán es una formula muy sencilla que puede dar mucho de sí.
Espero que os guste
Un saludo.