|
|||||||
|
|
|
![]() |
|
|
Strumenti |
|
|
#1 |
|
Senior Member
Iscritto dal: Mar 2003
Città: Rimini
Messaggi: 1846
|
[c] Run Lenght Encoding - suggerimenti per ottimizzazione
Ciao a tutti, ho fatto un programma molto semplice che ricevendo in input un file lo comprime o lo decomprime a seconda dell'estensione che ha.
Devo utilizzare il metodo rle: esempio file originale aaaabbcde esempio file compresso a4b2c1d1e1 Dal punto di vista pratico nel file compresso ci sono delle lettere scritte come char (1 byte) e dei numeri scritti come short int (2 byte). In questo modo se ho ad esempio una sequenza di 300 volte lo stesso carattere scrivendolo come short int occupa 3 byte (1 byte il carattere più 2 il numero di ripetizioni) mentre se usavo solo char ne avrebbe occupati 4. Il problema sorge a questo punto a causa della premessa implementativa che ho descritto sopra. Per ottimizzarlo potrei fare ad esempio così: a4bbcde cioè non scrivere il numero per le lettere con meno di 3 ripetizioni. Però a questo punto il decompressore come agisce? Il decompressore che ho fatto io legge sempre un char e poi uno short int che è il numero di ripetizioni perchè ogni carattere di fianco ha il numero. Se io lo tolgo per alcuni di questi come faccio poi a sapere cosa devo leggere? |
|
|
|
|
|
#2 |
|
Member
Iscritto dal: Aug 2005
Messaggi: 168
|
Laboratorio di programmazione con D'Angelo eh? Buona fortuna.
|
|
|
|
|
|
#3 |
|
Senior Member
Iscritto dal: Mar 2003
Città: Rimini
Messaggi: 1846
|
|
|
|
|
|
|
#4 |
|
Senior Member
Iscritto dal: Jul 2009
Città: Varès
Messaggi: 658
|
il decompressore deve fare uno scan di tutto il bytestream e ogni volta che incontra un intero n, fai partire un loop con n-1 cicli in cui inserisci in quel punto dello stream la lettera precedente al numero
|
|
|
|
|
|
#5 | |
|
Senior Member
Iscritto dal: May 2004
Città: Londra (Torino)
Messaggi: 3692
|
Quote:
Gia' in questo modo ho idea che si riduca notevolmente la lunghezza media del file compresso E inoltre in questo modo non hai piu' alcun problema per la ripetizione doppia
__________________
Se pensi che il tuo codice sia troppo complesso da capire senza commenti, e' segno che molto probabilmente il tuo codice e' semplicemente mal scritto. E se pensi di avere bisogno di un nuovo commento, significa che ti manca almeno un test. |
|
|
|
|
|
|
#6 | |
|
Senior Member
Iscritto dal: Mar 2003
Città: Rimini
Messaggi: 1846
|
Quote:
Il problema comunque è questo: il programma riceve un file qualsiasi di cui non si conosce la natura per cui è impensabile leggere un po' di char e un po' di short int. Potrei leggere solo char tanto per dire e poi se quello che ho letto non corrisponde ad una lettera dell'alfabeto (visto che nel file possono esserci solo lettere minuscole e spazi) allora lo rileggo come short int. Il problema è: e se per caso quello che leggo come char (1 byte) casualmente mi corrisponde ad una lettera minuscola ma è in realtà il primo dei due byte di uno short int? |
|
|
|
|
|
|
#7 | |
|
Senior Member
Iscritto dal: May 2004
Città: Londra (Torino)
Messaggi: 3692
|
Quote:
Comunque non proponevo di mettere limitazioni. Se ad esempio avessi bbb....bbb per 400 volte, lo comprimerei in b255b45 (Oppure b0b45, contando lo 0 come 256, essendo che il valore 0 non avrebbe alcun senso) per un totale di 4 bytes. bb invece semplicemente b2
__________________
Se pensi che il tuo codice sia troppo complesso da capire senza commenti, e' segno che molto probabilmente il tuo codice e' semplicemente mal scritto. E se pensi di avere bisogno di un nuovo commento, significa che ti manca almeno un test. |
|
|
|
|
|
|
#8 | ||
|
Member
Iscritto dal: Aug 2005
Messaggi: 168
|
Quote:
Quote:
|
||
|
|
|
|
|
#9 | |
|
Senior Member
Iscritto dal: Mar 2003
Città: Rimini
Messaggi: 1846
|
Quote:
Faccio un esempio semplice in cui non si va oltre le 256 ripetizioni. Dunque, se ho un file che è solo una sequenza di 200 a, in pratica scrivo su file un char 'a' e un intero '200' convertito in char che quindi occupa 1 byte. Poi leggo solo char e riconverto uno no e uno sì in interi? Così occupa solo due byte un file che a me ne avrebbe occupati 3. Però se poi ho un file 300 a e devo scrivere un char 'a' più un char '255' più un char 'a' più un char '45' mi occupa 4 byte invece di 3. Come banco di test ho anche file di 300 mega (cha tra l'altro mi impallano il pc e non riesco a usare) per cui suppongo ci siano all'interno ripetizioni molto lunghe. Posso provare ad implementarlo per vedere se ho capito bene la conversione dei tipi perchè mi sa che sto facendo un po' casino. Però mi rimane il problema che non posso evitare di scrivere il numero di ripetizioni nelle lettere che si presentano una volta sola. Ultima modifica di -Ivan- : 18-04-2010 alle 13:25. |
|
|
|
|
|
|
#10 |
|
Member
Iscritto dal: Jul 2008
Messaggi: 237
|
Edit: rimosso perché contrario al regolamento
Ultima modifica di cionci : 18-04-2010 alle 16:47. |
|
|
|
|
|
#11 |
|
Senior Member
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
|
!k-0t1c!: non si scrivono soluzioni per esercizi universitari.
Potresti fare in questo modo... Data una dimensione maggiore di 127 inserisci sempre un nuovo byte successivo al corrente. In pratica puoi utilizzare l'ultimo bit del byte come un flag che indica la presenza di un altro byte da leggere. Chiaramente la dimensione può anche andare fino a 5 byte (con un intero a 32 bit) o anche oltre (in teoria potresti contare anche simulando un intero a 64 bit con due interi a 32 bit). |
|
|
|
|
|
#12 |
|
Senior Member
Iscritto dal: Jan 2002
Città: Germania
Messaggi: 26110
|
E' concettualmente simile alla codifica utilizzata per l'UTF-8.
Ma per il dato problema non mi sento di consigliarla, e preferisco la soluzione di "gugo", che è molto più semplice da implementare e rimane abbastanza generale ed efficiente. In passato mi sono dedicato molto alla compressione dei dati (di qualunque natura), e debbo dire che molto, ma molto difficilmente i file presentano una "regolarità" tale da giustificare una codifica più complessa della classica RLE (che è stata comunque brevettata da un giapponese; ma penso che il brevetto sia ormai scaduto da tempo) con la coppia di byte lunghezza (da 1 a 256) + simbolo.
__________________
Per iniziare a programmare c'è solo Python con questo o quest'altro (più avanzato) libro @LinkedIn Non parlo in alcun modo a nome dell'azienda per la quale lavoro Ho poco tempo per frequentare il forum; eventualmente, contattatemi in PVT o nel mio sito. Fanboys |
|
|
|
|
|
#13 |
|
Senior Member
Iscritto dal: Nov 2005
Messaggi: 2782
|
Potresti rimappare i caratteri a-z più lo spazio nei valori da 0 a 26 ed usare i 229 valori rimanenti per i contatori.
Es: a a a b b c 97 97 97 98 98 99 diventa: a 3 b b c 0 29 1 1 2 oppure: a 3 b 2 c 0 29 1 28 2 EDIT: non avevo letto bene, devi usare 2 byte per il contatore... Forse si può comunque riadattare l'idea EDIT2: puoi usare i valori da 0 a 26 per i caratteri che hanno una sola occorrenza (quindi non c'è un contatore da leggere dopo) e i valori da 27 a 53 per i caratteri che precedono un contatore. Es: a a a b b c 97 97 97 98 98 99 diventa: a 3 b b c 27 00 29 1 1 2 (ho messo 00 solo per indicare che 29 occupa 2 byte invece di uno) Ultima modifica di wingman87 : 18-04-2010 alle 22:20. |
|
|
|
|
|
#14 | |
|
Member
Iscritto dal: Jul 2008
Messaggi: 237
|
Quote:
Inoltre l'implementazione che avevo proposto era a molto ingenua, avrebbe richiesto molto lavoro prima di essere presentabile ad un prof...senza contare che contavo deliberatamente solo fino a 255 per accertarmi che il copia-incolla fosse penalizzante |
|
|
|
|
|
|
#15 |
|
Senior Member
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
|
|
|
|
|
|
|
#16 |
|
Senior Member
Iscritto dal: Mar 2003
Città: Rimini
Messaggi: 1846
|
Grazie a tutti delle idee, sto prendendo un po' di qua e un po' di la per cercare di ottimizzare la cosa visto che il voto si basa sulla capacità di compressione ma anche sulla velocità impiegata.
Ultima modifica di -Ivan- : 19-04-2010 alle 18:53. |
|
|
|
|
|
#17 |
|
Senior Member
Iscritto dal: Oct 2001
Messaggi: 11471
|
Perché non usi un byte come escape che indica quando sta cominciando una sequenza di caratteri compressa? Ad esempio un '\0'. Se i caratteri sono ripetuti meno di 4 volte li copi così come sono altrimenti stampi il null, poi il carattere ripetuto e i due byte del short int con il numero di ripetizioni.
Dovrebbe scappare qualcosa di simile a questo (con i null al posto dei punti) .a5bbbcdbbccccbb.a6.e12ffcde.f6.e9 |
|
|
|
|
|
#18 | |
|
Senior Member
Iscritto dal: Mar 2003
Città: Rimini
Messaggi: 1846
|
Quote:
aaaaaabhhhhhhhcaaaaaaa mi vengono fuori tanti /0 ed alla fine non so se conviene o meno (anche perchè dovrei mettere un altro carattere una volta finita la sequenza compressa). Il problema è che non so come saranno strutturati i file da comprimere quindi non posso fare dei calcoli di convenienza. Però l'idea del /0 in effetti potrebbe farmi risparmiare il numero di fianco alle lettere singole. Vi chiedo un'altra cosa: secondo voi mi conviene fare come diceva !k-0t1c! cioè leggere il file e mettere tutto in memoria (una matrice di char) e poi elaborarla dopo? Perchè adesso come adesso io leggo un carattere da un file, eseguo calcoli e lo scrivo su file. Leggere tutto il file e memorizzarlo per poi elaborare la matrice e riscriverla non mi viene a costare di più in termini di tempo? I calcoli comunque sono fatti in memoria anche se per effettuarli ora deve attendere i tempi di lettura, però anche leggendo tutto prima non si annullano. Il file rimane comunque aperto non è che ogni volta devo fare l'operazione di riaprirlo. |
|
|
|
|
|
|
#19 |
|
Senior Member
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
|
Ti conviene leggere un buffer di dimensione pari ad un multiplo o un sottomultiplo dell'unità di allocazione minima del disco. Quindi 4096 byte dovrebbe essere perfetto.
Se trovi \0 nel file però è un po' complessa la cosa |
|
|
|
|
|
#20 | ||
|
Senior Member
Iscritto dal: Oct 2001
Messaggi: 11471
|
Quote:
Quote:
A spingersi ancora di più in la si potrebbe fare una scansione iniziale del file per vedere quale è il byte meno probabile ed usare quello come sequenza di escape. |
||
|
|
|
|
| Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 04:36.




















