Newsgroup: it.comp.lang.delphi
Titolo: Salvataggio di array bidimensionali...

Ho bisogno di poter fare salvataggi rapidi di array del tipo:
for j := 1 to 5 do
  for i := 1 to N [J] do T [i,j] := U [i,j];
Ho bisogno di velocita' in quanto il salvataggio deve essere fatto
milioni di volte.
Quando l'array era monodimensionale usavo fare semplicemente:
T := U o ancora piu' velocemente:
Move (U,T,n); (dove n non e' necessariamente la dimensione di T, ma
gli elementi diversi da zero).
Adesso che l'array e' bidimensionale non posso fare T := U in quanto
le dimensioni delle singole righe non sono uguali.
Per intenderci, la matrice puo' anche essere di 100x5 ma a me della
prima riga possono interessare (ed essere quindi salvati) solo i primi
5 elementi, della seconda solo i primi 10, della terza solo i primi 2,
etc etc.
Se salvassi ogni volta tutti i 500 elementi perderei un mucchio di
tempo perche' moltissimi saranno solo zeri.
Ho bisogno di un metodo rapido senza fare i 2 cicli for.
Spero di essere stato chiaro ;)
Grazie.
Paolo.

 Ho bisogno di un metodo rapido senza fare i 2 cicli for.
Non vedo quale attinenza abbia la tua richiesta con delphi.. fai 
ricerche su algoritmi e in altri gruppi piu' orientati al problem 
solving.. per quanto riguarda strettamente delphi ci sono librerie 
scritte con parti in ASM che sono preposte a velocizzare operazioni su 
stringhe, ordinamenti, ecc... di piu' non saprei dirti. Cerca in rete.
-- 
Morde

 Non vedo quale attinenza abbia la tua richiesta con delphi..
Perche' il programma e' scritto interamente in delphi, e se esiste un
certo tipo di istruzione "move" che puo' fare quello che cerco e' in
delphi che mi serve...
In realta' non mi serve un vero e proprio algoritmo, devo solo
velocizzare 2 cicli for, ma forse un'istruzione delphi che faccia
questo piu' velocemente non esiste.
Grazie.
Paolo.

  for i := 1 to N [J] do T [i,j] := U [i,j];
1) in caso non usare istruzioni 'for' ma 'while'.
2) dato che i vettori bidimensionali in memoria sono in effetti
monodimensionali penso ce la cosa piu' veloce sia in ogni caso usare
'move' senza provare a scartare i valori a 0 (a meno che la dimensione del
vettore sia enormemente piu' grande della sua parte valida)
3) se conosci in anticipo, prima di caricare il vettore, il numero di
elementi che ti servono usa vettori a dimensioni variabili
4) usa un profiler per misurare i tempi delle soluzioni provate. Io uso
ProDelphi ma ce ne sono anche di gratis ad esempio buono e' (era ?) GPProfile.
edoardo
--- posted by geoForum on 
http://www.delphiedintorni.it

 ProDelphi ma ce ne sono anche di gratis ad esempio buono e' (era ?) GPProfile.
Non ci avevo pensato; dato che i tempi erano dell'ordine di svariati
minuti, all'inizio della procedura avevo impostato un tempo di start,
ed alla fine della procedura avevo misurato il tempo. Comunque grazie
della dritta.
Saluti.
Paolo.

 monodimensionali...
Mi era venuto in mente un particolare importante:
Gli elementi diversi da zero (quelli che per me sono importanti da
salvare) sono solo quelli all'inizio della riga della matrice; tutti
gli altri sono inizializzati zero e non contano.
(esempio: riga 1:    1 4 7 8 0 0 0 0 0 ........0
               riga 2:    2 5 5 4 7 8 0 0 0 ........0
               riga 3:    3 8 0 0 0 0 0 0 0 ........0
               etc....)
La riga che contiene piu' elementi e' la riga 2 (contiene 6 elementi)
Decido di salvarne solo 6 per ogni riga:
Otterrei una matrice:
               riga 1:    1 4 7 8 0 0
               riga 2:    2 5 5 4 7 8
               riga 3:    3 8 0 0 0 0
               etc....)
Lo posso fare con un move ? E come ?
Saluti.
Paolo.

 Lo posso fare con un move ? E come ?
Mi rispondo da solo:
Move (U,T,6)
solo che vorrei anche trovare il modo per evitare di salvare i 6 o
piu' zeri che nell'esempio precedente devo per forza salvare.
Saluti.
Paolo.

serve *per forza* un array bidimensionale.
I vettori a dimensioni variabili possono essere anche bidimensionali


 
La struttura dati che devi usare si chiama "Matrice sparsa" che consente 
di memorizzare solo gli elementi che contengono un valore diverso da 
quello di default (0 nel tuo caso).
Ti consiglio anch'io, come ha già fatto Morde, di approfondire bene gli 
algoritmi e le strutture dati in generale; perché sono fondamentali per 
risolvere i problemi, indipendentemente dallo strumento/linguaggio che 
utilizzi realmente (Delphi nel tuo caso).
Giuseppe

 I vettori a dimensioni variabili possono essere anche bidimensionali
Posso chiederti un'esempio di dichiarazione di un'array bidimensionale
a dimensione variabile ?
Grazie mille.
Paolo.

 utilizzi realmente (Delphi nel tuo caso).
Grazie del consiglio; sono su google alla ricerca della chiave
"Matrice sparsa" che gentilissimamente mi hai suggerito.
Spero si sia capito che non sono "un'addetto ai lavori"; sono
programmatore delphi solo per hobby, i miei programmi non escono dalle
mura domestiche e per tutta la teoria che conosco sono solo
un'autodidatta.
Pero' sono soddisfatto del mio piccolo...
Grazie.
Saluti.
Paolo.

> La struttura dati che devi usare si chiama "Matrice sparsa" che consente
Il tuo non e' un caso di matrice sparsa in quanto i tuoi elementi validi
sono contigui a partire dalla prima posizione. Sarebbe meglio chiamarlo
vettore di liste.  Comunque per gestirlo in maniera piu' semplice e veloce
io proverei a gestirlo come una tabella di dimensioni variabili.
La matrice sparsa serve a sprecare meno memoria ma gli algoritmi su di
essa sono intrinsicamente lenti. Tu hai detto che il tuo problema e' la
velocita' ed allora la matrice sparsa sicuramente non ti serve.



In questo momento non ho delphi sotto mano ma mi ricordo che quando l'ho
usata avevo trovato la spiegazione nella guida di delphi.
Se non lo trovi domani vedro' di recuperare un esempio.


 velocita' ed allora la matrice sparsa sicuramente non ti serve.
Esatto, solo la velocita', altrimenti avrei bell'e usato i 2 cicli
for...
Saluti.
Paolo.

 Se non lo trovi domani vedro' di recuperare un esempio.
Ci conto; grazie.
Paolo.

la "Guida" e' la guida in linea di Delphi (vale a dire l'Help se preferisci)


 la "Guida" e' la guida in linea di Delphi (vale a dire l'Help se preferisci)
:)
Ci ho pensato subito dopo aver spedito il post. Li per li avevo
pensato alla guida cartacea.
Provo a cercarlo nell'help.
Grazie.
Paolo.



Se non ho capito male, la velocità non serve nei calcoli ma solo nel 
copiare la matrice. Considerando che una matrice sparsa può essere 
implementata con un normalissimo array monodimensionale, i cui elementi 
sono dei record con i campi "riga", "colonna" e "valore", direi che è 
possibile ottenere buone prestazioni copiando la matrice con la Move(...) 
che l'OP conosce già.
Giuseppe

 che l'OP conosce già.
Ok, siete stati tutti gentilissimi, quindi vorrei spiegarmi meglio.
*Prima* delle routine in cui serve velocita' ho gia' creato la
"struttura" della matrice, ovvero so dove ci sono gli zeri e so dove
ci saranno valori diversi da zero, ma *ancora non ne conosco il
valore*.
Poi cominciano le routine che bisogna velocizzare. Faccio i miei
calcoli ed inizio a mettere i valori calcolati (qui' le mie routine
vanno bene in fatto di velocita') nelle posizioni che conoscevo gia'.
Poi ho bisogno spesso di salvare detta matrice (o meglio le sole
posizioni diverse da zero) perche' se nei calcoli una variabile
booleana assume il valore false, devo riprendermi la matrice
precedentemente salvata (e questo devo farlo velocemente).
Nelle routine ho inoltre bisogno di lavorare sulla riga J-esima della
matrice, ma fino alla dimensione N [J] perche' so che da li in poi ci
saranno solo zeri.
L'idea dell'array a dimensioni variabili credo sia buona; se riesco a
dimensionarmi tali matrici (T ed U) all'inizio del programma con
dimensioni delle righe variabili N [J] in cui so che tutti i valori
sono quelli che mi servono (nessuno zero inutile per intenderci), per
salvare la matrice mi bastera' fare (correggetemi se sbaglio) T := U
ed in un colpo solo avro' salvato solo e soltanto i valori per me
utili.
Saluti.
Francesco.

Quanto segue e' stato preso dalla guida di D4.
Nota che puoi definire tabelle del tipo:
XXXXXX
XXXXXX
XXXXXX
XXXXXX
oppure
XXXX
XX
XXXXXX
XXX
Per il tuo problema io proverei ad usare la prima soluzione
scrivendo
XXXX00
XX0000
XXXXXX
XXX000
Avere una tabella con tutte le righe uguali permette di usare la move per
copiare la tabella senza inserire degli if per capire quali valori
prendere oppure non.
Con questa struttura regolare puoi anche facilmente implementare, se
preferisci, la tabella come un vettore.
edoardo
To declare multidimensional dynamic arrays, use iterated array of ...
constructions. For example,
type TMessageGrid = array of array of string;
var Msgs: TMessageGrid;
declares a two-dimensional array of strings. To instantiate this array,
call SetLength with two integer arguments. For example, if I and J are
integer-valued variables,
SetLength(Msgs,I,J);
allocates an I-by-J array, and Msgs[0,0] denotes an element of that array.
You can create multidimensional dynamic arrays that are not rectangular.
The first step is to call SetLength, passing it parameters for the first n
dimensions of the array. For example,
var Ints: array of array of Integer;
SetLength(Ints,10);
allocates ten rows for Ints but no columns. Later, you can allocate the
columns one at a time (giving them different lengths); for example
SetLength(Ints[2], 5);
makes the third column of Ints five integers long. At this point (even if
the other columns haven’t been allocated) you can assign values to the
third column—for example, Ints[2,4] := 6.
The following example uses dynamic arrays (and the IntToStr function
declared in the SysUtils unit) to create a triangular matrix of strings.
var
  A : array of array of string;
  I, J : Integer;
begin
  SetLength(A, 10);
  for I := Low(A) to High(A) do
  begin
    SetLength(A[I], I);
    for J := Low(A[I]) to High(A[I]) do
      A[I,J] := IntToStr(I) + ',' + IntToStr(J) + ' ';
  end;
end;


Morde ha scritto:

--------------
utilizza blockwrite().
Ciao
Pino
-- 
Questo articolo e` stato inviato dal sito web 
http://www.nonsolonews.it

Quanto segue e' stato preso dalla guida di D4.
Ieri sera ho poi risolto. :)))
Aveva ragione Giuseppe di Martino, dovevo usare un array
monodimensionale, e soprattutto aveva ragione Morde; questo problema
(col senno di poi, di una banalita' sconcertante) non aveva per nulla
attinenza col linguaggio delphi.
Il vettore monodimensionale che sto usando adesso e' composto in
sequenza da tutti gli elementi della matrice diversi da zero.
Devo pero' usare un puntatore P [1..5] che mi punti all'inizio della
"riga" J-esima all'interno del vettore monodimensionale.
L'i-esimo elemento della "riga virtuale" J sara':    T [P [J] + i]
E salvo il vettore usando un move semplicissimo (e soprattutto
veloce).
Grazie a tutti voi, era da un po' che cercavo di risolvere, e sono
sicuro che se non ne parlavo qui dentro, non ne venivo a capo.
E grazie mille anche a te edo; conservero' gelosamente le preziose
informazioni che mi hai fornito sugli array a lunghezza variabile.
Sono sicuro che da qualche altra parte ne avro' bisogno.
Saluti.
Paolo.

 gli elementi diversi da zero).
Se la memorizazione e' a tuo favore potresti provare cosi': dipende se la
componente i e' in sequenza, giorgio
For j:=1 to 5 do
    begin
    K:=N[j];
    Move(U[1,j], T[1,j], K);
    end;

     end;
Si, ci avevo pensato, ma volevo eliminare anche l'unico for...(A volte
sono proprio pignolo !).
Comunque ho risolto: vedi post di risposta ad edo del 12 dic.
Grazie mille.
Paolo.

Sono sicuro che da qualche altra parte ne avro' bisogno.
Invero ti sarebbero dovuti servire questa volta per salvare con un'unica
move tutta la tabella (abbinata ad informazione aggiuntiva num colonne e
righe) senza doverla scandire per capire quali sono gli elementi validi da
salvare insieme alle loro coordinate come invece hai fatto. 
Comunque hai risolto diversamente e va bene cosi'.
Ciao
edoardo


 salvare insieme alle loro coordinate come invece hai fatto.
Edo, il programma sta funzionando bene e finora ho perso rispetto a
prima (quando non avevo 5 righe di vettori, ma solo una) solo un 10%
di tempo in piu', che per me e' accettabilissimo.
La matrice (o piu' precisamente il vettore) viene salvato ora con
un'unico move, e tutta la scansione per trovare elementi validi e non,
viene effettuata all'inizio della procedura, solo la prima volta, e
non all'interno dei loop centrali milioni di volte.
Poi c'e' un'altra cosa che non ti ho detto (me ne sono vergognato un
po', credimi ;) ):
Lavoro con una vecchissima licenza di Delphi, addirittura la 3.0, e
questa non ha gli array che mi hai consigliato (mi sembra che li hanno
introdotto dalla 4 in poi).
Ho anche scaricato gratuitamente Turbodelphi Explorer, ma mi trovo
molto bene con la delphi 3 ed ancora non sono passato a Turbodelphi
definitivamente. D'altra parte per i programmini che faccio la 3 mi
basta e mi avanza.
Questo e' il motivo per cui, almeno per adesso, non ho usato gli array
che giustamente mi hai consigliato.
A presto.
Paolo.

introdotto dalla 4 in poi).
Io non sono messo molto meglio: lavoro con D4.
ciao
